Skip to content

Commit

Permalink
fix some thin wall issues.
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Jun 30, 2024
2 parents 9f974ef + 76110a5 commit 512b568
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 42 deletions.
6 changes: 3 additions & 3 deletions src/libslic3r/Fill/FillBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,9 @@ class ExtrusionSetRole : public ExtrusionVisitor {
ExtrusionSetRole(ExtrusionRole role) : new_role(role) {}
void use(ExtrusionPath &path) override { path.set_role(new_role); }
void use(ExtrusionPath3D &path3D) override { path3D.set_role(new_role); }
void use(ExtrusionMultiPath &multipath) override { for (ExtrusionPath path : multipath.paths) path.set_role(new_role); }
void use(ExtrusionMultiPath3D &multipath) override { for (ExtrusionPath path : multipath.paths) path.set_role(new_role); }
void use(ExtrusionLoop &loop) override { for (ExtrusionPath path : loop.paths) path.set_role(new_role); }
void use(ExtrusionMultiPath &multipath) override { for (ExtrusionPath &path : multipath.paths) path.set_role(new_role); }
void use(ExtrusionMultiPath3D &multipath) override { for (ExtrusionPath &path : multipath.paths) path.set_role(new_role); }
void use(ExtrusionLoop &loop) override { for (ExtrusionPath &path : loop.paths) path.set_role(new_role); }
void use(ExtrusionEntityCollection &collection) override { for (ExtrusionEntity *entity : collection.entities()) entity->visit(*this); }
};

Expand Down
11 changes: 7 additions & 4 deletions src/libslic3r/Fill/FillConcentric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,14 @@ FillConcentricWGapFill::fill_surface_extrusion(
// }
// //goto_next_polyline:
//}
if (!polylines.empty() && !is_bridge(good_role)) {
bool fill_bridge = is_bridge(good_role) || params.flow.bridge();
// allow bridged gapfill, mostly for support bottom interface.
assert(!is_bridge(good_role));
if (!polylines.empty()) {
ExtrusionEntitiesPtr gap_fill_entities = Geometry::thin_variable_width(polylines, erGapFill, params.flow, scale_t(params.config->get_computed_value("resolution_internal")), true);
if (!gap_fill_entities.empty()) {
//set role if needed
if (good_role != erSolidInfill) {
// set role if needed
if (fill_bridge || (good_role != erSolidInfill && good_role != erTopSolidInfill)) {
ExtrusionSetRole set_good_role(good_role);
for (ExtrusionEntity* ptr : gap_fill_entities)
ptr->visit(set_good_role);
Expand Down Expand Up @@ -395,7 +398,7 @@ FillConcentricWGapFill::fill_surface_extrusion(
// external gapfill
ExPolygons gapfill_areas = diff_ex(ExPolygons{ surface->expolygon }, offset_ex(expp, double(scale_(0.5 * this->get_spacing()))));
gapfill_areas = union_safety_offset_ex(gapfill_areas);
if (gapfill_areas.size() > 0) {
if (gapfill_areas.size() > 0 && no_overlap_expolygons.size() > 0) {
double minarea = double(params.flow.scaled_width()) * double(params.flow.scaled_width());
if (params.config != nullptr) minarea = scale_d(params.config->gap_fill_min_area.get_abs_value(params.flow.width())) * double(params.flow.scaled_width());
for (int i = 0; i < gapfill_areas.size(); i++) {
Expand Down
67 changes: 35 additions & 32 deletions src/libslic3r/Geometry/MedialAxis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2636,17 +2636,15 @@ MedialAxis::taper_ends(ThickPolylines& pp)
if (polyline.length() < length * 2.2) continue;
if (polyline.endpoints.first) {
polyline.points_width[0] = min_size;
coord_t current_dist = min_size;
coord_t last_dist = min_size;
coord_t current_dist = 0;
coord_t last_dist = 0;
for (size_t i = 1; i < polyline.points_width.size(); ++i) {
current_dist += (coord_t)polyline.points[i - 1].distance_to(polyline.points[i]);
if (current_dist > length) {
//create a new point if not near enough
if (current_dist > length + coordf_t(this->m_resolution)) {
coordf_t percent_dist = (length - last_dist) / (current_dist - last_dist);
polyline.points.insert(polyline.points.begin() + i, polyline.points[i - 1].interpolate(percent_dist, polyline.points[i]));
polyline.points_width.insert(polyline.points_width.begin() + i, polyline.points_width[i]);
}
coordf_t percent_dist = (length - last_dist) / (current_dist - last_dist);
polyline.points.insert(polyline.points.begin() + i, polyline.points[i - 1].interpolate(percent_dist, polyline.points[i]));
polyline.points_width.insert(polyline.points_width.begin() + i, polyline.points_width[i]);
break;
}
polyline.points_width[i] = std::max((coordf_t)min_size, min_size + (polyline.points_width[i] - min_size) * current_dist / length);
Expand All @@ -2655,17 +2653,15 @@ MedialAxis::taper_ends(ThickPolylines& pp)
}
if (polyline.endpoints.second) {
polyline.points_width[polyline.points_width.size() - 1] = min_size;
coord_t current_dist = min_size;
coord_t last_dist = min_size;
coord_t current_dist = 0;
coord_t last_dist = 0;
for (size_t i = polyline.points_width.size() - 1; i > 0; --i) {
current_dist += (coord_t)polyline.points[i].distance_to(polyline.points[i - 1]);
if (current_dist > length) {
//create new point if not near enough
if (current_dist > length + coordf_t(this->m_resolution)) {
coordf_t percent_dist = (length - last_dist) / (current_dist - last_dist);
polyline.points.insert(polyline.points.begin() + i, polyline.points[i].interpolate(percent_dist, polyline.points[i - 1]));
polyline.points_width.insert(polyline.points_width.begin() + i, polyline.points_width[i - 1]);
}
coordf_t percent_dist = (length - last_dist) / (current_dist - last_dist);
polyline.points.insert(polyline.points.begin() + i, polyline.points[i].interpolate(percent_dist, polyline.points[i - 1]));
polyline.points_width.insert(polyline.points_width.begin() + i, polyline.points_width[i - 1]);
break;
}
polyline.points_width[i - 1] = std::max((coordf_t)min_size, min_size + (polyline.points_width[i - 1] - min_size) * current_dist / length);
Expand Down Expand Up @@ -3114,25 +3110,23 @@ unsafe_variable_width(const ThickPolyline& polyline, const ExtrusionRole role, c
continue;
}
} else if (i > 0 && resolution_internal > line_len + prev_line_len) {
assert(prev_line_len > 0 && line_len > 0);
//merge lines?
//if it's a loop, merge only if the distance is high enough
if (polyline.first_point() == polyline.last_point() && polyline.length() < (line_len + prev_line_len) * 6)
continue;
ThickLine& prev_line = lines[i - 1];
const coordf_t sum_length = prev_line_len + line_len;
const coordf_t new_length = prev_line.a.distance_to(line.b);
assert(sum_length - new_length > -0.0000000001);
// only merge if the distance is almost the sum (90° = 0.707)
if(new_length < sum_length * 0.9)
continue;
assert(new_length > prev_line_len && new_length > line_len);
coordf_t width = prev_line_len * (prev_line.a_width + prev_line.b_width) / 2;
width += line_len * (line.a_width + line.b_width) / 2;
width /= (prev_line_len + line_len);
prev_line.b = line.b;
const coordf_t new_length = prev_line.length();
if (new_length < SCALED_EPSILON) {
// too short, remove it and restart
if (i > 1) {
line.a = lines[i - 2].b;
}
lines.erase(lines.begin() + i - 1);
i -= 2;
continue;
}
width /= new_length;
prev_line.a_width = width;
prev_line.b_width = width;
saved_line_len = new_length;
Expand All @@ -3154,6 +3148,7 @@ unsafe_variable_width(const ThickPolyline& polyline, const ExtrusionRole role, c
// but we can't extrude with a negative spacing, so we have to gradually fall back to spacing if the width is too small.

// default: extrude a thin wall that doesn't go outside of the specified width.
assert(line.a_width == line.b_width);
double wanted_width = unscaled(line.a_width);
//if gapfill or arachne, the width is in fact the spacing.
if (role != erThinWall) {
Expand All @@ -3163,21 +3158,25 @@ unsafe_variable_width(const ThickPolyline& polyline, const ExtrusionRole role, c
} else {
// Convert from spacing to extrusion width based on the extrusion model
// of a square extrusion ended with semi circles.
wanted_width = Flow::rounded_rectangle_extrusion_width_from_spacing(unscaled(line.a_width), flow.height(), flow.spacing_ratio());
wanted_width = Flow::rounded_rectangle_extrusion_width_from_spacing(wanted_width, flow.height(), flow.spacing_ratio());
}
}
// check if the width isn't too small (negative spacing)
// 1.f spacing ratio, because it's to get the really minimum. 0 spacing ratio will makes that irrelevant.
if (unscale<coordf_t>(line.a_width) < 2 * Flow::rounded_rectangle_extrusion_width_from_spacing(0.f, flow.height(), 1.f)) {
if (wanted_width < 2 * Flow::rounded_rectangle_extrusion_width_from_spacing(0.f, flow.height(), 1.f)) {
//width (too) small, be sure to not extrude with negative spacing.
//we began to fall back to spacing gradually even before the spacing go into the negative
// to make extrusion1 < extrusion2 if width1 < width2 even if width2 is too small.
wanted_width = unscaled(line.a_width) * 0.35 + 1.3 * Flow::rounded_rectangle_extrusion_width_from_spacing(0.f, flow.height(), 1.f);
// to make extrusion1 < extrusion2 if width1 < width2 even if width2 is too small.
wanted_width = wanted_width * 0.35 + 1.3 * Flow::rounded_rectangle_extrusion_width_from_spacing(0.f, flow.height(), 1.f);
}

if (path.polyline.empty()) {
if (wanted_width != current_flow.width()) {
current_flow = current_flow.with_width((float)wanted_width);
if (current_flow.bridge()) {
current_flow = Flow::bridging_flow(current_flow.height(), (float) wanted_width);
} else {
current_flow = current_flow.with_width((float) wanted_width);
}
}
path.polyline.append(line.a);
path.polyline.append(line.b);
Expand All @@ -3198,7 +3197,11 @@ unsafe_variable_width(const ThickPolyline& polyline, const ExtrusionRole role, c
paths.push_back(path);
path = ExtrusionPath(role, false);
if (wanted_width != current_flow.width()) {
current_flow = current_flow.with_width(wanted_width);
if (current_flow.bridge()) {
current_flow = Flow::bridging_flow(current_flow.height(), (float) wanted_width);
} else {
current_flow = current_flow.with_width((float) wanted_width);
}
}
path.polyline.append(line.a);
path.polyline.append(line.b);
Expand Down Expand Up @@ -3226,7 +3229,7 @@ ExtrusionEntitiesPtr
// 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 coord_t tolerance = flow.scaled_width() / 10;//scale_(0.05);
const coord_t tolerance = flow.scaled_width() / 20;//scale_(0.05);
ExtrusionEntitiesPtr coll;
for (const ThickPolyline& p : polylines) {
ExtrusionMultiPath multi_paths = variable_width(p, role, flow, resolution_internal, tolerance, can_reverse);
Expand Down
9 changes: 6 additions & 3 deletions src/libslic3r/PerimeterGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1579,7 +1579,7 @@ ProcessSurfaceResult PerimeterGenerator::process_classic(int& contour_count, int
bound.remove_point_too_near(ext_perimeter_width / 10);
// the maximum thickness of our thin wall area is equal to the minimum thickness of a single loop (*1.2 because of circles approx. and enlrgment from 'div')
Slic3r::Geometry::MedialAxis ma{ thin[0], (coord_t)((ext_perimeter_width + ext_perimeter_spacing) * 1.2),
min_width, coord_t(this->layer->height) };
min_width, scale_t(this->layer->height) };
ma.use_bounds(bound)
.use_min_real_width(scale_t(this->ext_perimeter_flow.nozzle_diameter()))
.use_tapers(thin_walls_overlap)
Expand Down Expand Up @@ -3687,9 +3687,12 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
if (searcher.search_result.path != nullptr) {
#if _DEBUG
searcher.search_result.loop->visit(LoopAssertVisitor{});
ExtrusionLoop orig_loop = *searcher.search_result.loop;
#endif
if (!searcher.search_result.from_start)
tw.reverse();
//save old path, as it may be destroyed before being re-created and we want to keep its parameters.
ExtrusionPath path_to_split = *searcher.search_result.path; // TODO: 2.7: just save hte pathsettigns
//get the point
Point point = tw.front().projection_onto(searcher.search_result.line);
//we have to create 3 paths: 1: thinwall extusion, 2: thinwall return, 3: end of the path
Expand Down Expand Up @@ -3749,14 +3752,14 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
} else {
assert(poly_after.length() > SCALED_EPSILON);
searcher.search_result.loop->paths.insert(searcher.search_result.loop->paths.begin() + idx_path_to_add,
ExtrusionPath(poly_after, *searcher.search_result.path));
ExtrusionPath(poly_after, path_to_split));
}
assert(idx_path_before > searcher.search_result.loop->paths.size() || searcher.search_result.loop->paths[idx_path_before].polyline.size() > 1);
assert(poly_after.size() > 0);

//create thin wall path exttrusion
ExtrusionEntityCollection tws;
tws.append(Geometry::thin_variable_width({ tw }, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)), false));
tws.append(Geometry::thin_variable_width({ tw }, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 10, scale_t(this->print_config->resolution)), false));
assert(!tws.entities().empty());
#if _DEBUG
tws.visit(LoopAssertVisitor{});
Expand Down

0 comments on commit 512b568

Please sign in to comment.