mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 09:15:57 +08:00
Thin_wall / medial axis:
- reworked thin_variable_width (discretization into segments of constant width) - bugfix taper_ends - add setting thin_walls_overlap to control the perimeter/thin wall overlap
This commit is contained in:
parent
bc0b249803
commit
75775bc909
@ -111,6 +111,7 @@ void Layer::make_perimeters()
|
||||
&& 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.thin_walls_overlap == other_config.thin_walls_overlap
|
||||
&& config.external_perimeters_first == other_config.external_perimeters_first
|
||||
&& config.perimeter_loop == other_config.perimeter_loop) {
|
||||
layerms.push_back(other_layerm);
|
||||
|
@ -343,13 +343,8 @@ add_point_same_percent(ThickPolyline* pattern, ThickPolyline* to_modify)
|
||||
double percent_dist = (percent_length - percent_length_other_before) / (percent_length_other - percent_length_other_before);
|
||||
coordf_t new_width = to_modify->width[idx_other - 1] * (1 - percent_dist);
|
||||
new_width += to_modify->width[idx_other] * (percent_dist);
|
||||
Point new_point;
|
||||
new_point.x() = (coord_t)((double)(to_modify->points[idx_other - 1].x()) * (1 - percent_dist));
|
||||
new_point.x() += (coord_t)((double)(to_modify->points[idx_other].x()) * (percent_dist));
|
||||
new_point.y() = (coord_t)((double)(to_modify->points[idx_other - 1].y()) * (1 - percent_dist));
|
||||
new_point.y() += (coord_t)((double)(to_modify->points[idx_other].y()) * (percent_dist));
|
||||
to_modify->width.insert(to_modify->width.begin() + idx_other, new_width);
|
||||
to_modify->points.insert(to_modify->points.begin() + idx_other, new_point);
|
||||
to_modify->points.insert(to_modify->points.begin() + idx_other, to_modify->points[idx_other - 1].interpolate(percent_dist, to_modify->points[idx_other]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1049,14 +1044,11 @@ MedialAxis::remove_too_thin_extrusion(ThickPolylines& pp)
|
||||
while (polyline.points.size() > 1 && polyline.width.front() < this->min_width && polyline.endpoints.first) {
|
||||
//try to split if possible
|
||||
if (polyline.width[1] > min_width) {
|
||||
double percent_can_keep = 1 - (min_width - polyline.width[0]) / (polyline.width[1] - polyline.width[0]);
|
||||
if (polyline.points.front().distance_to(polyline.points[1]) * percent_can_keep > SCALED_RESOLUTION) {
|
||||
double percent_can_keep = (min_width - polyline.width[0]) / (polyline.width[1] - polyline.width[0]);
|
||||
if (polyline.points.front().distance_to(polyline.points[1]) * (1-percent_can_keep) > SCALED_RESOLUTION) {
|
||||
//Can split => move the first point and assign a new weight.
|
||||
//the update of endpoints wil be performed in concatThickPolylines
|
||||
polyline.points.front().x() = polyline.points.front().x() +
|
||||
(coord_t)((polyline.points[1].x() - polyline.points.front().x()) * (1 - percent_can_keep));
|
||||
polyline.points.front().y() = polyline.points.front().y() +
|
||||
(coord_t)((polyline.points[1].y() - polyline.points.front().y()) * (1 - percent_can_keep));
|
||||
polyline.points.front() = polyline.points.front().interpolate(percent_can_keep, polyline.points[1]);
|
||||
polyline.width.front() = min_width;
|
||||
} else {
|
||||
/// almost 0-length, Remove
|
||||
@ -1073,14 +1065,11 @@ MedialAxis::remove_too_thin_extrusion(ThickPolylines& pp)
|
||||
while (polyline.points.size() > 1 && polyline.width.back() < this->min_width && polyline.endpoints.second) {
|
||||
//try to split if possible
|
||||
if (polyline.width[polyline.points.size() - 2] > min_width) {
|
||||
double percent_can_keep = 1 - (min_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]) * percent_can_keep > SCALED_RESOLUTION) {
|
||||
double percent_can_keep = (min_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) > SCALED_RESOLUTION) {
|
||||
//Can split => move the first point and assign a new weight.
|
||||
//the update of endpoints wil be performed in concatThickPolylines
|
||||
polyline.points.back().x() = polyline.points.back().x() +
|
||||
(coord_t)((polyline.points[polyline.points.size() - 2].x() - polyline.points.back().x()) * (1 - percent_can_keep));
|
||||
polyline.points.back().y() = polyline.points.back().y() +
|
||||
(coord_t)((polyline.points[polyline.points.size() - 2].y() - polyline.points.back().y()) * (1 - percent_can_keep));
|
||||
polyline.points.back() = polyline.points.back().interpolate(percent_can_keep, polyline.points[polyline.points.size() - 2]);
|
||||
polyline.width.back() = min_width;
|
||||
} else {
|
||||
/// almost 0-length, Remove
|
||||
@ -1108,6 +1097,7 @@ void
|
||||
MedialAxis::concatenate_polylines_with_crossing(ThickPolylines& pp)
|
||||
{
|
||||
|
||||
|
||||
// concatenate, but even where multiple thickpolyline join, to create nice long strait polylines
|
||||
/* If we removed any short polylines we now try to connect consecutive polylines
|
||||
in order to allow loop detection. Note that this algorithm is greedier than
|
||||
@ -1155,7 +1145,11 @@ MedialAxis::concatenate_polylines_with_crossing(ThickPolylines& pp)
|
||||
best_dot = other_dot;
|
||||
}
|
||||
}
|
||||
if (best_candidate != nullptr) {
|
||||
if (best_candidate != nullptr && best_candidate->size() > 1) {
|
||||
//intersections may create ever-ertusion because the included circle can be a bit larger. We have to make it short again.
|
||||
if (polyline.width.back() > polyline.width[polyline.width.size() - 2] && polyline.width.back() > best_candidate->width[1]) {
|
||||
polyline.width.back() = std::min(polyline.width[polyline.width.size() - 2], best_candidate->width[1]);
|
||||
}
|
||||
polyline.points.insert(polyline.points.end(), best_candidate->points.begin() + 1, best_candidate->points.end());
|
||||
polyline.width.insert(polyline.width.end(), best_candidate->width.begin() + 1, best_candidate->width.end());
|
||||
polyline.endpoints.second = best_candidate->endpoints.second;
|
||||
@ -1455,7 +1449,6 @@ MedialAxis::build(ThickPolylines* polylines_out) {
|
||||
// svg.draw(pp);
|
||||
// svg.Close();
|
||||
//}
|
||||
|
||||
concatenate_polylines_with_crossing(pp);
|
||||
//{
|
||||
// stringstream stri;
|
||||
@ -1518,26 +1511,49 @@ MedialAxis::grow_to_nozzle_diameter(ThickPolylines& pp, const ExPolygons& anchor
|
||||
|
||||
void
|
||||
MedialAxis::taper_ends(ThickPolylines& pp) {
|
||||
const coord_t min_size = this->nozzle_diameter * 0.1;
|
||||
const coordf_t length = std::min(this->anchor_size, (this->nozzle_diameter - min_size) / 2);
|
||||
if (length <= SCALED_RESOLUTION) return;
|
||||
//ensure the width is not lower than 0.4.
|
||||
for (ThickPolyline& polyline : pp) {
|
||||
if (polyline.length() < nozzle_diameter * 2) continue;
|
||||
if (polyline.length() < length * 2.2) continue;
|
||||
if (polyline.endpoints.first) {
|
||||
polyline.width[0] = min_width;
|
||||
coord_t current_dist = min_width;
|
||||
polyline.width[0] = min_size;
|
||||
coord_t current_dist = min_size;
|
||||
coord_t last_dist = min_size;
|
||||
for (size_t i = 1; i<polyline.width.size(); ++i) {
|
||||
current_dist += (coord_t) polyline.points[i - 1].distance_to(polyline.points[i]);
|
||||
if (current_dist > polyline.width[i]) break;
|
||||
polyline.width[i] = current_dist;
|
||||
if (current_dist > length) {
|
||||
//create new point if not near enough
|
||||
if (current_dist > polyline.width[i] + SCALED_RESOLUTION) {
|
||||
coordf_t percent_dist = (polyline.width[i] - polyline.width[i - 1]) / (current_dist - last_dist);
|
||||
polyline.points.insert(polyline.points.begin() + i, polyline.points[i - 1].interpolate(percent_dist, polyline.points[i]));
|
||||
polyline.width.insert(polyline.width.begin() + i, polyline.width[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
polyline.width[i] = std::max((coordf_t)min_size, min_size + (polyline.width[i] - min_size) * current_dist / length);
|
||||
last_dist = current_dist;
|
||||
}
|
||||
}
|
||||
if (polyline.endpoints.second) {
|
||||
size_t last_idx = polyline.width.size() - 1;
|
||||
polyline.width[last_idx] = min_width;
|
||||
coord_t current_dist = min_width;
|
||||
const size_t back_idx = polyline.width.size() - 1;
|
||||
polyline.width[back_idx] = min_size;
|
||||
coord_t current_dist = min_size;
|
||||
coord_t last_dist = min_size;
|
||||
for (size_t i = 1; i<polyline.width.size(); ++i) {
|
||||
current_dist += (coord_t) polyline.points[last_idx - i + 1].distance_to(polyline.points[last_idx - i]);
|
||||
if (current_dist > polyline.width[last_idx - i]) break;
|
||||
polyline.width[last_idx - i] = current_dist;
|
||||
current_dist += (coord_t)polyline.points[back_idx - i + 1].distance_to(polyline.points[back_idx - i]);
|
||||
if (current_dist > length) {
|
||||
//create new point if not near enough
|
||||
if (current_dist > polyline.width[back_idx - i] + SCALED_RESOLUTION) {
|
||||
coordf_t percent_dist = (polyline.width[back_idx - i] - polyline.width[back_idx - i + 1]) / (current_dist - last_dist);
|
||||
polyline.points.insert(polyline.points.begin() + back_idx - i + 1, polyline.points[back_idx - i + 1].interpolate(percent_dist, polyline.points[back_idx - i]));
|
||||
polyline.width.insert(polyline.width.begin() + back_idx - i + 1, polyline.width[back_idx - i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
polyline.width[back_idx - i] = std::max((coordf_t)min_size, min_size + (polyline.width[back_idx - i] - min_size) * current_dist / length);
|
||||
last_dist = current_dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1547,65 +1563,67 @@ ExtrusionEntityCollection thin_variable_width(const ThickPolylines &polylines, E
|
||||
// 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
|
||||
// of segments, and any pruning shall be performed before we apply this tolerance
|
||||
const double tolerance = scale_(0.05);
|
||||
const double tolerance = 4*SCALED_RESOLUTION;//scale_(0.05);
|
||||
|
||||
int id_line = 0;
|
||||
ExtrusionEntityCollection coll;
|
||||
for (const ThickPolyline &p : polylines) {
|
||||
id_line++;
|
||||
ExtrusionPaths paths;
|
||||
ExtrusionPath path(role);
|
||||
ThickLines lines = p.thicklines();
|
||||
|
||||
for (int i = 0; i < (int)lines.size(); ++i) {
|
||||
const ThickLine& line = lines[i];
|
||||
ThickLine& line = lines[i];
|
||||
|
||||
const coordf_t line_len = line.length();
|
||||
if (line_len < SCALED_EPSILON) continue;
|
||||
|
||||
double thickness_delta = fabs(line.a_width - line.b_width);
|
||||
if (thickness_delta > tolerance) {
|
||||
const uint16_t segments = (uint16_t) std::min(16000.0, ceil(thickness_delta / tolerance));
|
||||
const coordf_t seg_len = line_len / segments;
|
||||
if (thickness_delta > tolerance && ceil(thickness_delta / tolerance) > 2) {
|
||||
const uint16_t segments = 1+(uint16_t) std::min(16000.0, ceil(thickness_delta / tolerance));
|
||||
Points pp;
|
||||
std::vector<coordf_t> width;
|
||||
{
|
||||
pp.push_back(line.a);
|
||||
width.push_back(line.a_width);
|
||||
for (size_t j = 1; j < segments; ++j) {
|
||||
pp.push_back(line.point_at(j*seg_len));
|
||||
|
||||
coordf_t w = line.a_width + (j*seg_len) * (line.b_width - line.a_width) / line_len;
|
||||
width.push_back(w);
|
||||
width.push_back(w);
|
||||
for (size_t j = 0; j < segments; ++j) {
|
||||
pp.push_back(line.a.interpolate(((double)j) / segments, line.b));
|
||||
double percent_width = ((double)j) / (segments-1);
|
||||
width.push_back(line.a_width*(1 - percent_width) + line.b_width*percent_width);
|
||||
}
|
||||
pp.push_back(line.b);
|
||||
width.push_back(line.b_width);
|
||||
|
||||
assert(pp.size() == segments + 1);
|
||||
assert(width.size() == segments * 2);
|
||||
assert(width.size() == segments);
|
||||
}
|
||||
|
||||
// delete this line and insert new ones
|
||||
lines.erase(lines.begin() + i);
|
||||
for (size_t j = 0; j < segments; ++j) {
|
||||
ThickLine new_line(pp[j], pp[j + 1]);
|
||||
new_line.a_width = width[2 * j];
|
||||
new_line.b_width = width[2 * j + 1];
|
||||
new_line.a_width = width[j];
|
||||
new_line.b_width = width[j];
|
||||
lines.insert(lines.begin() + i + j, new_line);
|
||||
}
|
||||
|
||||
--i;
|
||||
continue;
|
||||
} else if (thickness_delta > 0) {
|
||||
//create a middle point
|
||||
ThickLine new_line(line.a.interpolate(0.5, line.b), line.b);
|
||||
new_line.a_width = line.b_width;
|
||||
new_line.b_width = line.b_width;
|
||||
line.b = new_line.a;
|
||||
line.b_width = line.a_width;
|
||||
lines.insert(lines.begin() + i + 1, new_line);
|
||||
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
const double w = std::fmax(line.a_width, line.b_width);
|
||||
if (path.polyline.points.empty()) {
|
||||
path.polyline.append(line.a);
|
||||
path.polyline.append(line.b);
|
||||
// Convert from spacing to extrusion width based on the extrusion model
|
||||
// of a square extrusion ended with semi circles.
|
||||
flow.width = (float)unscaled(w) + flow.height * (1. - 0.25 * PI);
|
||||
flow.width = (float)unscaled(line.a_width) + flow.height * (1. - 0.25 * PI);
|
||||
#ifdef SLIC3R_DEBUG
|
||||
printf(" filling %f gap\n", flow.width);
|
||||
#endif
|
||||
@ -1613,7 +1631,7 @@ ExtrusionEntityCollection thin_variable_width(const ThickPolylines &polylines, E
|
||||
path.width = flow.width;
|
||||
path.height = flow.height;
|
||||
} else {
|
||||
thickness_delta = fabs(scale_(flow.width) - w);
|
||||
thickness_delta = fabs(flow.scaled_spacing() - line.a_width);
|
||||
if (thickness_delta <= tolerance / 2) {
|
||||
// the width difference between this line and the current flow width is
|
||||
// within the accepted tolerance
|
||||
|
@ -25,10 +25,12 @@ namespace Slic3r {
|
||||
const coord_t min_width;
|
||||
const coord_t height;
|
||||
coord_t nozzle_diameter;
|
||||
coord_t anchor_size;
|
||||
bool stop_at_min_width = true;
|
||||
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;
|
||||
anchor_size = 0;
|
||||
};
|
||||
void build(ThickPolylines* polylines_out);
|
||||
void build(Polylines* polylines);
|
||||
|
@ -228,7 +228,7 @@ void PerimeterGenerator::process()
|
||||
}
|
||||
|
||||
// Calculate next onion shell of perimeters.
|
||||
//this variable stored the nexyt onion
|
||||
//this variable stored the next onion
|
||||
ExPolygons next_onion;
|
||||
if (i == 0) {
|
||||
// compute next onion, without taking care of thin_walls : destroy too thin areas.
|
||||
@ -240,23 +240,21 @@ void PerimeterGenerator::process()
|
||||
if (this->config->thin_walls) {
|
||||
// the minimum thickness of a single loop is:
|
||||
// ext_width/2 + ext_spacing/2 + spacing/2 + width/2
|
||||
|
||||
next_onion = offset2_ex(
|
||||
last,
|
||||
-(float)(ext_perimeter_width / 2 + ext_min_spacing / 2 - 1),
|
||||
+(float)(ext_min_spacing / 2 - 1));
|
||||
|
||||
// detect edge case where a curve can be split in multiple small chunks.
|
||||
ExPolygons no_thin_onion = offset_ex(last, -(float)(ext_perimeter_width / 2));
|
||||
float div = 2;
|
||||
while (no_thin_onion.size() > 0 && next_onion.size() > no_thin_onion.size() && no_thin_onion.size() + next_onion.size() > 3) {
|
||||
div += 0.5;
|
||||
//use a sightly smaller spacing to try to drastically improve the split
|
||||
//use a sightly smaller spacing to try to drastically improve the split, but with a little bit of over-extrusion
|
||||
ExPolygons next_onion_secondTry = offset2_ex(
|
||||
last,
|
||||
-(float)(ext_perimeter_width / 2 + ext_min_spacing / div - 1),
|
||||
+(float)(ext_min_spacing / div - 1));
|
||||
if (next_onion.size() > next_onion_secondTry.size()) {
|
||||
if (next_onion.size() > next_onion_secondTry.size() * 1.1) {
|
||||
next_onion = next_onion_secondTry;
|
||||
}
|
||||
if (div > 3) break;
|
||||
@ -281,13 +279,13 @@ void PerimeterGenerator::process()
|
||||
no_thin_zone = diff_ex(last, offset_ex(half_thins, (float)(min_width / 2) - (float) SCALED_EPSILON), true);
|
||||
}
|
||||
// compute a bit of overlap to anchor thin walls inside the print.
|
||||
ExPolygons thin_zones_extruded;
|
||||
for (ExPolygon &half_thin : half_thins) {
|
||||
//growing back the polygon
|
||||
ExPolygons thin = offset_ex(half_thin, (float)(min_width / 2));
|
||||
assert(thin.size() == 1);
|
||||
coord_t 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, (float)(min_width / 2) +
|
||||
(float)(ext_perimeter_width / 2), jtSquare), no_thin_zone, true);
|
||||
(float)(overlap), jtSquare), no_thin_zone, true);
|
||||
ExPolygons bounds = union_ex(thin, anchor, true);
|
||||
for (ExPolygon &bound : bounds) {
|
||||
if (!intersection_ex(thin[0], bound).empty()) {
|
||||
@ -298,14 +296,13 @@ void PerimeterGenerator::process()
|
||||
// the maximum thickness of our thin wall area is equal to the minimum thickness of a single loop
|
||||
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.anchor_size = overlap;
|
||||
ma.build(&thin_walls);
|
||||
thin_zones_extruded.emplace_back(thin[0]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
next_onion = diff_ex(offset_ex(last, -(float)(ext_perimeter_width / 2)), thin_zones_extruded, true);
|
||||
}
|
||||
} else {
|
||||
//FIXME Is this offset correct if the line width of the inner perimeters differs
|
||||
|
@ -209,6 +209,19 @@ Point Point::projection_onto(const Line &line) const
|
||||
return ((line.a - *this).cast<double>().squaredNorm() < (line.b - *this).cast<double>().squaredNorm()) ? line.a : line.b;
|
||||
}
|
||||
|
||||
/// This method create a new point on the line defined by this and p2.
|
||||
/// The new point is place at position defined by |p2-this| * percent, starting from this
|
||||
/// \param percent the proportion of the segment length to place the point
|
||||
/// \param p2 the second point, forming a segment with this
|
||||
/// \return a new point, == this if percent is 0 and == p2 if percent is 1
|
||||
Point Point::interpolate(const double percent, const Point &p2) const
|
||||
{
|
||||
Point p_out;
|
||||
p_out.x() = this->x()*(1 - percent) + p2.x()*(percent);
|
||||
p_out.y() = this->y()*(1 - percent) + p2.y()*(percent);
|
||||
return p_out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &stm, const Vec2d &pointf)
|
||||
{
|
||||
return stm << pointf(0) << "," << pointf(1);
|
||||
|
@ -121,6 +121,7 @@ public:
|
||||
double ccw_angle(const Point &p1, const Point &p2) const;
|
||||
Point projection_onto(const MultiPoint &poly) const;
|
||||
Point projection_onto(const Line &line) const;
|
||||
Point interpolate(const double percent, const Point &p) const;
|
||||
|
||||
double distance_to(const Point &point) const { return (point - *this).cast<double>().norm(); }
|
||||
double distance_to_square(const Point &point) const {
|
||||
|
@ -2426,7 +2426,16 @@ void PrintConfigDef::init_fff_params()
|
||||
def->cli = "thin-walls-min-width=s";
|
||||
def->mode = comExpert;
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloatOrPercent(33,true);
|
||||
def->default_value = new ConfigOptionFloatOrPercent(33, true);
|
||||
|
||||
def = this->add("thin_walls_overlap", coFloatOrPercent);
|
||||
def->label = L("overlap");
|
||||
def->category = L("Layers and Perimeters");
|
||||
def->tooltip = L("Overlap between the thin wall and the perimeters. Can be a % of the external perimeter width (default 50%)");
|
||||
def->cli = "thin-walls-overlap=s";
|
||||
def->mode = comExpert;
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloatOrPercent(50, true);
|
||||
|
||||
def = this->add("threads", coInt);
|
||||
def->label = L("Threads");
|
||||
|
@ -573,6 +573,7 @@ public:
|
||||
// Detect thin walls.
|
||||
ConfigOptionBool thin_walls;
|
||||
ConfigOptionFloatOrPercent thin_walls_min_width;
|
||||
ConfigOptionFloatOrPercent thin_walls_overlap;
|
||||
ConfigOptionFloatOrPercent top_infill_extrusion_width;
|
||||
ConfigOptionInt top_solid_layers;
|
||||
ConfigOptionFloatOrPercent top_solid_infill_speed;
|
||||
@ -629,6 +630,7 @@ protected:
|
||||
OPT_PTR(solid_infill_speed);
|
||||
OPT_PTR(thin_walls);
|
||||
OPT_PTR(thin_walls_min_width);
|
||||
OPT_PTR(thin_walls_overlap);
|
||||
OPT_PTR(top_infill_extrusion_width);
|
||||
OPT_PTR(top_solid_infill_speed);
|
||||
OPT_PTR(top_solid_layers);
|
||||
|
@ -463,6 +463,7 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
||||
|| opt_key == "infill_overlap"
|
||||
|| opt_key == "thin_walls"
|
||||
|| opt_key == "thin_walls_min_width"
|
||||
|| opt_key == "thin_walls_overlap"
|
||||
|| opt_key == "external_perimeters_first"
|
||||
|| opt_key == "perimeter_loop"
|
||||
|| opt_key == "perimeter_loop_seam"
|
||||
|
@ -360,6 +360,7 @@ const std::vector<std::string>& Preset::print_options()
|
||||
, "infill_not_connected"
|
||||
, "first_layer_infill_speed"
|
||||
, "thin_walls_min_width"
|
||||
, "thin_walls_overlap"
|
||||
};
|
||||
return s_opts;
|
||||
}
|
||||
|
@ -945,6 +945,7 @@ void TabPrint::build()
|
||||
line = { _(L("Thin walls")), "" };
|
||||
line.append_option(optgroup->get_option("thin_walls"));
|
||||
line.append_option(optgroup->get_option("thin_walls_min_width"));
|
||||
line.append_option(optgroup->get_option("thin_walls_overlap"));
|
||||
optgroup->append_line(line);
|
||||
optgroup->append_single_option_line("overhangs");
|
||||
line = { _(L("Avoid unsupported perimeters")), "" };
|
||||
@ -1363,11 +1364,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", "thin_walls_min_width",
|
||||
"seam_position", "external_perimeters_first", "external_perimeter_extrusion_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"));
|
||||
for (auto el : { "thin_walls_min_width", "thin_walls_overlap" }) get_field(el)->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