Fix gap - infill voids

This commit is contained in:
supermerill 2021-10-29 19:37:09 +02:00
parent 08cd7ebe26
commit 5c0bf45bc1

View File

@ -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, &not_filled_p); ex.simplify_p(SCALED_RESOLUTION, &not_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, &not_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();
}*/ }*/