mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-13 15:59:00 +08:00
gap fill: remove gap fill if it's too thin to make a continuous curve.
thinwall/gapfill: remove harmful bits that sticks out of the main line without going outside of it.
This commit is contained in:
parent
e380bd9176
commit
daa891aa9b
@ -558,6 +558,67 @@ MedialAxis::fusion_curve(ThickPolylines &pp)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MedialAxis::remove_bits(ThickPolylines &pp)
|
||||
{
|
||||
|
||||
//remove small bits that stick out of the path
|
||||
bool changes = false;
|
||||
for (size_t i = 0; i < pp.size(); ++i) {
|
||||
ThickPolyline& polyline = pp[i];
|
||||
// only consider polyline with 0-end
|
||||
if (polyline.endpoints.first) polyline.reverse();
|
||||
else if (!polyline.endpoints.second) continue;
|
||||
if (polyline.width.back() > 0) continue;
|
||||
|
||||
//check my length is small
|
||||
coord_t length = (coord_t)polyline.length();
|
||||
if (length > max_width*1.5) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// look if other end is a cross point with multiple other branch
|
||||
std::vector<size_t> crosspoint;
|
||||
for (size_t j = 0; j < pp.size(); ++j) {
|
||||
if (j == i) continue;
|
||||
ThickPolyline& other = pp[j];
|
||||
if (polyline.first_point().coincides_with(other.last_point())) {
|
||||
other.reverse();
|
||||
crosspoint.push_back(j);
|
||||
} else if (polyline.first_point().coincides_with(other.first_point())) {
|
||||
crosspoint.push_back(j);
|
||||
}
|
||||
}
|
||||
if (crosspoint.size() < 2) continue;
|
||||
|
||||
//check if is smaller or the other ones are not endpoits
|
||||
int nb_better_than_me = 0;
|
||||
for (int i = 0; i < crosspoint.size(); i++) {
|
||||
if (!pp[crosspoint[0]].endpoints.second || length <= pp[crosspoint[0]].length())
|
||||
nb_better_than_me++;
|
||||
}
|
||||
if (nb_better_than_me < 2) continue;
|
||||
|
||||
//check if the length of the polyline is small vs width of the other lines
|
||||
double max_width = 0;
|
||||
for (int i = 0; i < crosspoint.size(); i++) {
|
||||
max_width = std::max(max_width, pp[crosspoint[i]].width[0]);
|
||||
}
|
||||
if (length > max_width + min_width)
|
||||
continue;
|
||||
|
||||
//delete the now unused polyline
|
||||
pp.erase(pp.begin() + i);
|
||||
--i;
|
||||
changes = true;
|
||||
}
|
||||
if (changes) {
|
||||
concatThickPolylines(pp);
|
||||
///reorder, in case of change
|
||||
std::sort(pp.begin(), pp.end(), [](const ThickPolyline & a, const ThickPolyline & b) { return a.length() < b.length(); });
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MedialAxis::fusion_corners(ThickPolylines &pp)
|
||||
{
|
||||
@ -567,7 +628,7 @@ MedialAxis::fusion_corners(ThickPolylines &pp)
|
||||
for (size_t i = 0; i < pp.size(); ++i) {
|
||||
ThickPolyline& polyline = pp[i];
|
||||
// only consider polyline with 0-end
|
||||
if (polyline.points.size() != 2) continue;
|
||||
//if (polyline.points.size() != 2) continue; // maybe we should have something to merge X-point to 2-point if it's near enough.
|
||||
if (polyline.endpoints.first) polyline.reverse();
|
||||
else if (!polyline.endpoints.second) continue;
|
||||
if (polyline.width.back() > 0) continue;
|
||||
@ -1717,6 +1778,10 @@ MedialAxis::build(ThickPolylines &polylines_out)
|
||||
// svg.Close();
|
||||
//}
|
||||
|
||||
remove_bits(pp);
|
||||
|
||||
//sort_polylines(pp);
|
||||
|
||||
//for (auto &p : pp) {
|
||||
// std::cout << " polyline : ";
|
||||
// for (auto &w : p.width) {
|
||||
|
@ -112,6 +112,8 @@ class MedialAxis {
|
||||
void taper_ends(ThickPolylines& pp);
|
||||
//cleaning method
|
||||
void check_width(ThickPolylines& pp, double max_width, std::string msg);
|
||||
//removing small extrusion that won't be useful and will harm print. A bit like fusion_corners but more lenient and with just del.
|
||||
void remove_bits(ThickPolylines& pp);
|
||||
};
|
||||
|
||||
/// create a ExtrusionEntityCollection from ThickPolylines, discretizing the variable width into little sections (of 4*SCALED_RESOLUTION length) where needed.
|
||||
|
@ -677,18 +677,55 @@ void PerimeterGenerator::process()
|
||||
//be sure we don't gapfill where the perimeters are already touching each other (negative spacing).
|
||||
min = std::max(min, double(Flow::new_from_spacing(EPSILON, nozzle_diameter, this->layer_height, false).scaled_width()));
|
||||
double max = 2.2 * perimeter_spacing;
|
||||
ExPolygons gaps_ex = diff_ex(
|
||||
offset2_ex(gaps, double(-min / 2), double(+min / 2)),
|
||||
//remove areas that are too big (shouldn't occur...)
|
||||
ExPolygons gaps_ex_to_test = diff_ex(
|
||||
gaps,
|
||||
offset2_ex(gaps, double(-max / 2), double(+max / 2)),
|
||||
true);
|
||||
ThickPolylines polylines;
|
||||
for (const ExPolygon &ex : gaps_ex) {
|
||||
ExPolygons gaps_ex;
|
||||
const double minarea = scale_(scale_(this->config->gap_fill_min_area.get_abs_value(unscaled(perimeter_width)*unscaled(perimeter_width))));
|
||||
// check each gapfill area to see if it's printable.
|
||||
for (const ExPolygon &expoly : gaps_ex_to_test) {
|
||||
//remove too small gaps that are too hard to fill.
|
||||
//ie one that are smaller than an extrusion with width of min and a length of max.
|
||||
if (ex.area() > scale_(scale_(this->config->gap_fill_min_area.get_abs_value(unscaled(perimeter_width)*unscaled(perimeter_width))))) {
|
||||
MedialAxis{ ex, coord_t(max*1.1), coord_t(min), coord_t(this->layer_height) }.build(polylines);
|
||||
if (expoly.area() > minarea) {
|
||||
ExPolygons expoly_after_shrink_test = offset_ex(ExPolygons{ expoly }, double(-min * 0.5));
|
||||
//if the shrink split the area in multipe bits
|
||||
if (expoly_after_shrink_test.size() > 1) {
|
||||
//remove too small bits
|
||||
for (int i = 0; i < expoly_after_shrink_test.size(); i++)
|
||||
if (offset_ex(ExPolygons{ expoly_after_shrink_test[i] }, min*0.5)[0].area() < minarea) {
|
||||
expoly_after_shrink_test.erase(expoly_after_shrink_test.begin() + i);
|
||||
i--;
|
||||
}
|
||||
//maybe some areas are a just bit too thin, try with just a little more offset to remove them.
|
||||
ExPolygons expoly_after_shrink_test2 = offset_ex(ExPolygons{ expoly }, double(-min *0.8));
|
||||
for (int i = 0; i < expoly_after_shrink_test2.size(); i++)
|
||||
if (offset_ex(ExPolygons{ expoly_after_shrink_test2[i] }, min*0.5)[0].area() < minarea) {
|
||||
expoly_after_shrink_test2.erase(expoly_after_shrink_test2.begin() + i);
|
||||
i--;
|
||||
}
|
||||
//it's better if there are significantly less extrusions
|
||||
if (expoly_after_shrink_test.size()/1.42 > expoly_after_shrink_test2.size()) {
|
||||
expoly_after_shrink_test2 = offset_ex(expoly_after_shrink_test2, double(min * 0.8));
|
||||
//insert with move instead of copy
|
||||
std::move(expoly_after_shrink_test2.begin(), expoly_after_shrink_test2.end(), std::back_inserter(gaps_ex));
|
||||
} else {
|
||||
expoly_after_shrink_test = offset_ex(expoly_after_shrink_test, double(min * 0.8));
|
||||
std::move(expoly_after_shrink_test.begin(), expoly_after_shrink_test.end(), std::back_inserter(gaps_ex));
|
||||
}
|
||||
} else {
|
||||
expoly_after_shrink_test = offset_ex(expoly_after_shrink_test, double(min * 0.8));
|
||||
std::move(expoly_after_shrink_test.begin(), expoly_after_shrink_test.end(), std::back_inserter(gaps_ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
// create lines from the area
|
||||
ThickPolylines polylines;
|
||||
for (const ExPolygon &ex : gaps_ex) {
|
||||
MedialAxis{ ex, coord_t(max*1.1), coord_t(min), coord_t(this->layer_height) }.build(polylines);
|
||||
}
|
||||
// create extrusion from lines
|
||||
if (!polylines.empty()) {
|
||||
ExtrusionEntityCollection gap_fill = thin_variable_width(polylines,
|
||||
erGapFill, this->solid_infill_flow);
|
||||
@ -704,6 +741,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.
|
||||
|
||||
// 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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user