diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 73a48f2a7..8c1ac78f5 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1593,10 +1593,10 @@ void PrintObject::bridge_over_infill() double bridge_angle; }; - std::unordered_map> briding_surfaces; + std::unordered_map> bridging_surfaces; tbb::parallel_for(tbb::blocked_range(0, this->layers().size()), [po = this, - &briding_surfaces](tbb::blocked_range r) { + &bridging_surfaces](tbb::blocked_range r) { for (size_t lidx = r.begin(); lidx < r.end(); lidx++) { const Layer *layer = po->get_layer(lidx); @@ -1628,21 +1628,19 @@ void PrintObject::bridge_over_infill() SurfacesPtr region_internal_solids = region->fill_surfaces().filter_by_type(stInternalSolid); // remove very small solid infills, usually not worth it and many of them may not even contain extrusions in the end. - region_internal_solids - .erase(std::remove_if(region_internal_solids.begin(), region_internal_solids.end(), - [slice_island_tree, region](const Surface *s) { - float min_width = float(region->bridging_flow(frSolidInfill).scaled_spacing()) * 3.f; - if (slice_island_tree.distance_from_lines(s->expolygon.contour.first_point()) > - min_width / 3.0) { - return true; - } - return area(offset_ex({s->expolygon}, -min_width)) < - min_width * region->bridging_flow(frSolidInfill).scaled_width(); - }), - region_internal_solids.end()); + region_internal_solids.erase(std::remove_if(region_internal_solids.begin(), region_internal_solids.end(), + [slice_island_tree, region](const Surface *s) { + float spacing = float( + region->bridging_flow(frSolidInfill, true).scaled_spacing()); + if (slice_island_tree.outside(s->expolygon.contour.first_point()) > 0) { + return true; + } + return offset({s->expolygon}, -3.0 * spacing).empty(); + }), + region_internal_solids.end()); if (!region_internal_solids.empty()) { max_bridge_flow_height[&slice] = std::max(max_bridge_flow_height[&slice], - region->bridging_flow(frSolidInfill).height()); + region->bridging_flow(frSolidInfill, true).height()); } for (const Surface *s : region_internal_solids) { surface_to_region[s] = region; @@ -1688,8 +1686,9 @@ void PrintObject::bridge_over_infill() }; // Gather lower layers sparse infill areas, to depth defined by used bridge flow - Polygons lower_layers_sparse_infill{}; - Polygons special_infill{}; + Polygons lower_layers_sparse_infill{}; + Polygons special_infill{}; + Polygons not_sparse_infill{}; { double bottom_z = layer->print_z - max_bridge_flow_height[candidates.first] - EPSILON; LayerSlice::Links current_links = candidates.first->overlaps_below; @@ -1715,15 +1714,18 @@ void PrintObject::bridge_over_infill() } for (const LayerRegion *region : regions_under_to_check) { - if (region->region().config().fill_density.value < 100 && !region_has_special_infill(region)) { - for (const Surface *surface : region->fill_surfaces().filter_by_type(stInternal)) { - Polygons p = to_polygons(surface->expolygon); + bool has_low_density = region->region().config().fill_density.value < 100; + bool has_special_infill = region_has_special_infill(region); + for (const Surface &surface : region->fill_surfaces()) { + if (surface.surface_type == stInternal && has_low_density && !has_special_infill) { + Polygons p = to_polygons(surface.expolygon); lower_layers_sparse_infill.insert(lower_layers_sparse_infill.end(), p.begin(), p.end()); - } - } else if (region_has_special_infill(region)) { - for (const Surface *surface : region->fill_surfaces().filter_by_type(stInternal)) { - Polygons p = to_polygons(surface->expolygon); + } else if (surface.surface_type == stInternal && has_low_density && has_special_infill) { + Polygons p = to_polygons(surface.expolygon); special_infill.insert(special_infill.end(), p.begin(), p.end()); + } else { + Polygons p = to_polygons(surface.expolygon); + not_sparse_infill.insert(not_sparse_infill.end(), p.begin(), p.end()); } } } @@ -1733,11 +1735,13 @@ void PrintObject::bridge_over_infill() lower_layers_sparse_infill = intersection(lower_layers_sparse_infill, layer->lslices[int(candidates.first - layer->lslices_ex.data())]); + lower_layers_sparse_infill = diff(lower_layers_sparse_infill, not_sparse_infill); special_infill = intersection(special_infill, layer->lslices[int(candidates.first - layer->lslices_ex.data())]); + special_infill = diff(special_infill, not_sparse_infill); lower_layers_sparse_infill.insert(lower_layers_sparse_infill.end(), special_infill.begin(), special_infill.end()); - if (lower_layers_sparse_infill.empty()) { + if (shrink(lower_layers_sparse_infill, 6.0 * scaled(max_bridge_flow_height[candidates.first])).empty()) { continue; } } @@ -1745,7 +1749,7 @@ void PrintObject::bridge_over_infill() if (expansion_space[candidates.first].empty() && special_infill.empty()) { // there is no expansion space to which can anchors expand on this island, add back original polygons and skip the island for (const Surface *candidate : candidates.second) { - briding_surfaces[candidates.first].emplace_back(candidate, to_polygons(candidate->expolygon), + bridging_surfaces[candidates.first].emplace_back(candidate, to_polygons(candidate->expolygon), surface_to_region[candidate], 0); } continue; @@ -1763,14 +1767,14 @@ void PrintObject::bridge_over_infill() // bridging. These areas we then expand (within the surrounding sparse infill only!) // to touch the infill polylines on previous layer. for (const Surface *candidate : candidates.second) { - const Flow &flow = surface_to_region[candidate]->bridging_flow(frSolidInfill); + const Flow &flow = surface_to_region[candidate]->bridging_flow(frSolidInfill, true); assert(candidate->surface_type == stInternalSolid); - Polygons bridged_area = to_polygons(candidate->expolygon); + Polygons bridged_area = expand(to_polygons(candidate->expolygon), flow.scaled_spacing()); bridged_area = intersection(bridged_area, lower_layers_sparse_infill); // cut off parts which are not over sparse infill - material overflow - if (area(shrink(bridged_area, 3.0 * flow.scaled_spacing())) < 9.0 * flow.scaled_spacing() * flow.scaled_spacing()) { + if (shrink(bridged_area, 4.0 * flow.scaled_spacing()).empty()) { continue; } @@ -2052,7 +2056,7 @@ void PrintObject::bridge_over_infill() expanded_bridged_area = opening(expanded_bridged_area, flow.scaled_spacing()); expand_area = diff(expand_area, expanded_bridged_area); - briding_surfaces[candidates.first].emplace_back(candidate, expanded_bridged_area, surface_to_region[candidate], + bridging_surfaces[candidates.first].emplace_back(candidate, expanded_bridged_area, surface_to_region[candidate], bridging_angle); #ifdef DEBUG_BRIDGE_OVER_INFILL debug_draw(std::to_string(lidx) + "cadidate_added", to_lines(expanded_bridged_area), to_lines(bridged_area), @@ -2066,13 +2070,13 @@ void PrintObject::bridge_over_infill() BOOST_LOG_TRIVIAL(info) << "Bridge over infill - Directions and expanded surfaces computed" << log_memory_info(); tbb::parallel_for(tbb::blocked_range(0, this->layers().size()), [po = this, - &briding_surfaces](tbb::blocked_range r) { + &bridging_surfaces](tbb::blocked_range r) { for (size_t lidx = r.begin(); lidx < r.end(); lidx++) { Layer *layer = po->get_layer(lidx); for (const LayerSlice &slice : layer->lslices_ex) { - if (const auto &modified_surfaces = briding_surfaces.find(&slice); - modified_surfaces != briding_surfaces.end()) { + if (const auto &modified_surfaces = bridging_surfaces.find(&slice); + modified_surfaces != bridging_surfaces.end()) { std::unordered_set regions_to_check; for (const LayerIsland &island : slice.islands) { regions_to_check.insert(layer->regions()[island.perimeters.region()]);