mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 19:35:55 +08:00
Fix gap - infill voids
This commit is contained in:
parent
08cd7ebe26
commit
5c0bf45bc1
@ -450,6 +450,7 @@ void PerimeterGenerator::process()
|
|||||||
std::vector<PerimeterGeneratorLoops> contours(loop_number + 1); // depth => loops
|
std::vector<PerimeterGeneratorLoops> contours(loop_number + 1); // depth => loops
|
||||||
std::vector<PerimeterGeneratorLoops> holes(loop_number + 1); // depth => loops
|
std::vector<PerimeterGeneratorLoops> holes(loop_number + 1); // depth => loops
|
||||||
ThickPolylines thin_walls;
|
ThickPolylines thin_walls;
|
||||||
|
ExPolygons no_last_gapfill;
|
||||||
// we loop one time more than needed in order to find gaps after the last perimeter was applied
|
// we loop one time more than needed in order to find gaps after the last perimeter was applied
|
||||||
for (int i = 0;; ++i) { // outer loop is 0
|
for (int i = 0;; ++i) { // outer loop is 0
|
||||||
|
|
||||||
@ -643,15 +644,17 @@ void PerimeterGenerator::process()
|
|||||||
// look for gaps
|
// look for gaps
|
||||||
if (this->config->gap_fill
|
if (this->config->gap_fill
|
||||||
//check if we are going to have an other perimeter
|
//check if we are going to have an other perimeter
|
||||||
&& (i <= loop_number || has_overhang || next_onion.empty() || (this->config->gap_fill_last.value && i == loop_number+1)))
|
&& (i <= loop_number || has_overhang || next_onion.empty() || (this->config->gap_fill_last.value && i == loop_number + 1))) {
|
||||||
// not using safety offset here would "detect" very narrow gaps
|
// not using safety offset here would "detect" very narrow gaps
|
||||||
// (but still long enough to escape the area threshold) that gap fill
|
// (but still long enough to escape the area threshold) that gap fill
|
||||||
// won't be able to fill but we'd still remove from infill area
|
// won't be able to fill but we'd still remove from infill area
|
||||||
append(gaps, diff_ex(
|
no_last_gapfill = offset_ex(next_onion, 0.5f * good_spacing + 10,
|
||||||
offset(last, -0.5f * gap_fill_spacing),
|
|
||||||
offset(next_onion, 0.5f * good_spacing + 10,
|
|
||||||
(round_peri ? ClipperLib::JoinType::jtRound : ClipperLib::JoinType::jtMiter),
|
(round_peri ? ClipperLib::JoinType::jtRound : ClipperLib::JoinType::jtMiter),
|
||||||
(round_peri ? min_round_spacing : 3)))); // safety offset
|
(round_peri ? min_round_spacing : 3));
|
||||||
|
append(gaps, diff_ex(
|
||||||
|
offset_ex(last, -0.5f * gap_fill_spacing),
|
||||||
|
no_last_gapfill)); // safety offset
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next_onion.empty()) {
|
if (next_onion.empty()) {
|
||||||
@ -993,6 +996,8 @@ void PerimeterGenerator::process()
|
|||||||
} // for each loop of an island
|
} // for each loop of an island
|
||||||
|
|
||||||
// fill gaps
|
// fill gaps
|
||||||
|
ExPolygons gaps_ex;
|
||||||
|
ExPolygons gap_srf;
|
||||||
if (!gaps.empty()) {
|
if (!gaps.empty()) {
|
||||||
// collapse
|
// collapse
|
||||||
double min = 0.2 * perimeter_width * (1 - INSET_OVERLAP_TOLERANCE);
|
double min = 0.2 * perimeter_width * (1 - INSET_OVERLAP_TOLERANCE);
|
||||||
@ -1002,7 +1007,6 @@ void PerimeterGenerator::process()
|
|||||||
//remove areas that are too big (shouldn't occur...)
|
//remove areas that are too big (shouldn't occur...)
|
||||||
ExPolygons too_big = offset2_ex(gaps, double(-max / 2), double(+max / 2));
|
ExPolygons too_big = offset2_ex(gaps, double(-max / 2), double(+max / 2));
|
||||||
ExPolygons gaps_ex_to_test = too_big.empty() ? gaps : diff_ex(gaps, too_big, true);
|
ExPolygons gaps_ex_to_test = too_big.empty() ? gaps : diff_ex(gaps, too_big, true);
|
||||||
ExPolygons gaps_ex;
|
|
||||||
const double minarea = scale_(scale_(this->config->gap_fill_min_area.get_abs_value(unscaled((double)perimeter_width) * unscaled((double)perimeter_width))));
|
const double minarea = scale_(scale_(this->config->gap_fill_min_area.get_abs_value(unscaled((double)perimeter_width) * unscaled((double)perimeter_width))));
|
||||||
// check each gapfill area to see if it's printable.
|
// check each gapfill area to see if it's printable.
|
||||||
for (const ExPolygon& expoly : gaps_ex_to_test) {
|
for (const ExPolygon& expoly : gaps_ex_to_test) {
|
||||||
@ -1071,9 +1075,11 @@ void PerimeterGenerator::process()
|
|||||||
are not subtracted from fill surfaces (they might be too short gaps
|
are not subtracted from fill surfaces (they might be too short gaps
|
||||||
that medial axis skips but infill might join with other infill regions
|
that medial axis skips but infill might join with other infill regions
|
||||||
and use zigzag). */
|
and use zigzag). */
|
||||||
//FIXME Vojtech: This grows by a rounded extrusion width, not by line spacing,
|
// get clean surface of gap
|
||||||
// therefore it may cover the area, but no the volume.
|
gap_srf = union_ex(offset(gap_fill.polygons_covered_by_width(float(SCALED_EPSILON) / 10), float(SCALED_EPSILON / 2)));
|
||||||
last = diff_ex(to_polygons(last), gap_fill.polygons_covered_by_width(10.f));
|
// intersection to ignore the bits of gapfill tha may be over infill, as it's epsilon and there may be some voids here anyway.
|
||||||
|
gap_srf = intersection_ex(gap_srf, gaps_ex);
|
||||||
|
// the diff(last, gap) will be done after, as we have to keep the last un-gapped to avoid unneeded gap/infill offset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//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.
|
//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.
|
||||||
@ -1093,23 +1099,46 @@ void PerimeterGenerator::process()
|
|||||||
if (inset == 0) {
|
if (inset == 0) {
|
||||||
infill_peri_overlap = 0;
|
infill_peri_overlap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//remove gapfill from last
|
||||||
|
ExPolygons last_no_gaps = (gap_srf.empty()) ? last : diff_ex(last, gap_srf);
|
||||||
|
|
||||||
// simplify infill contours according to resolution
|
// simplify infill contours according to resolution
|
||||||
Polygons not_filled_p;
|
Polygons not_filled_p;
|
||||||
for (ExPolygon &ex : last)
|
for (ExPolygon& ex : last_no_gaps)
|
||||||
ex.simplify_p(SCALED_RESOLUTION, ¬_filled_p);
|
ex.simplify_p(SCALED_RESOLUTION, ¬_filled_p);
|
||||||
ExPolygons not_filled_exp = union_ex(not_filled_p);
|
ExPolygons not_filled_exp = union_ex(not_filled_p);
|
||||||
// collapse too narrow infill areas
|
// collapse too narrow infill areas
|
||||||
coord_t min_perimeter_infill_spacing = (coord_t)(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
coord_t min_perimeter_infill_spacing = (coord_t)(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||||
// append infill areas to fill_surfaces
|
ExPolygons infill_exp;
|
||||||
//auto it_surf = this->fill_surfaces->surfaces.end();
|
//special branch if gap : don't inset away from gaps!
|
||||||
ExPolygons infill_exp = offset2_ex(not_filled_exp,
|
if (gap_srf.empty())
|
||||||
|
infill_exp = offset2_ex(not_filled_exp,
|
||||||
double(-inset - min_perimeter_infill_spacing / 2 + infill_peri_overlap - infill_gap),
|
double(-inset - min_perimeter_infill_spacing / 2 + infill_peri_overlap - infill_gap),
|
||||||
double(min_perimeter_infill_spacing / 2));
|
double(min_perimeter_infill_spacing / 2));
|
||||||
|
else {
|
||||||
|
//store the infill_exp but not offseted, it will be used as a clip to remove the gapfill portion
|
||||||
|
const ExPolygons infill_exp_no_gap = offset2_ex(not_filled_exp,
|
||||||
|
double(-inset - min_perimeter_infill_spacing / 2 + infill_peri_overlap - infill_gap),
|
||||||
|
double(inset + min_perimeter_infill_spacing / 2 - infill_peri_overlap + infill_gap));
|
||||||
|
//redo the same as not_filled_exp but with last instead of last_no_gaps
|
||||||
|
not_filled_p.clear();
|
||||||
|
for (ExPolygon& ex : last)
|
||||||
|
ex.simplify_p(SCALED_RESOLUTION, ¬_filled_p);
|
||||||
|
not_filled_exp = union_ex(not_filled_p);
|
||||||
|
infill_exp = offset2_ex(not_filled_exp,
|
||||||
|
double(-inset - min_perimeter_infill_spacing / 2 + infill_peri_overlap - infill_gap),
|
||||||
|
double(min_perimeter_infill_spacing / 2));
|
||||||
|
// intersect(growth(last-gap) , last), so you have the (last - small gap) but without voids betweeng gap & last
|
||||||
|
infill_exp = intersection_ex(infill_exp, infill_exp_no_gap);
|
||||||
|
}
|
||||||
|
|
||||||
//if any top_fills, grow them by ext_perimeter_spacing/2 to have the real un-anchored fill
|
//if any top_fills, grow them by ext_perimeter_spacing/2 to have the real un-anchored fill
|
||||||
ExPolygons top_infill_exp = intersection_ex(fill_clip, offset_ex(top_fills, double(ext_perimeter_spacing / 2)));
|
ExPolygons top_infill_exp = intersection_ex(fill_clip, offset_ex(top_fills, double(ext_perimeter_spacing / 2)));
|
||||||
if (!top_fills.empty()) {
|
if (!top_fills.empty()) {
|
||||||
infill_exp = union_ex(infill_exp, offset_ex(top_infill_exp, double(infill_peri_overlap)));
|
infill_exp = union_ex(infill_exp, offset_ex(top_infill_exp, double(infill_peri_overlap)));
|
||||||
}
|
}
|
||||||
|
// append infill areas to fill_surfaces
|
||||||
this->fill_surfaces->append(infill_exp, stPosInternal | stDensSparse);
|
this->fill_surfaces->append(infill_exp, stPosInternal | stDensSparse);
|
||||||
|
|
||||||
if (infill_peri_overlap != 0) {
|
if (infill_peri_overlap != 0) {
|
||||||
@ -1128,14 +1157,15 @@ void PerimeterGenerator::process()
|
|||||||
}
|
}
|
||||||
this->fill_no_overlap.insert(this->fill_no_overlap.end(), polyWithoutOverlap.begin(), polyWithoutOverlap.end());
|
this->fill_no_overlap.insert(this->fill_no_overlap.end(), polyWithoutOverlap.begin(), polyWithoutOverlap.end());
|
||||||
/*{
|
/*{
|
||||||
|
static int isaqsdsdfsdfqzfn = 0;
|
||||||
std::stringstream stri;
|
std::stringstream stri;
|
||||||
stri << this->layer->id() << "_2_end_makeperimeter_" << this->layer->id() << ".svg";
|
stri << this->layer->id() << "_2_end_makeperimeter_" << isaqsdsdfsdfqzfn++ << ".svg";
|
||||||
SVG svg(stri.str());
|
SVG svg(stri.str());
|
||||||
svg.draw(to_polylines(infill_exp), "blue");
|
svg.draw(to_polylines(infill_exp), "blue");
|
||||||
svg.draw(to_polylines(fill_no_overlap), "cyan");
|
svg.draw(to_polylines(fill_no_overlap), "cyan");
|
||||||
svg.draw(to_polylines(not_filled_exp), "green");
|
svg.draw(to_polylines(not_filled_exp), "green");
|
||||||
svg.draw(to_polylines(last), "yellow");
|
svg.draw(to_polylines(last_no_gaps), "yellow");
|
||||||
svg.draw(to_polylines(offset_ex(fill_clip, ext_perimeter_spacing / 2)), "yellow");
|
svg.draw(to_polylines(offset_ex(fill_clip, ext_perimeter_spacing / 2)), "brown");
|
||||||
svg.draw(to_polylines(top_infill_exp), "orange");
|
svg.draw(to_polylines(top_infill_exp), "orange");
|
||||||
svg.Close();
|
svg.Close();
|
||||||
}*/
|
}*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user