Parallelized PrintObject::bridge_over_infill() (#2132)

Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com>
This commit is contained in:
Noisyfox 2023-09-17 11:22:11 +08:00 committed by GitHub
parent bd13d83385
commit 685e058c35
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 40 deletions

View file

@ -1728,61 +1728,70 @@ void PrintObject::discover_vertical_shells()
// PROFILE_OUTPUT(debug_out_path("discover_vertical_shells-profile.txt").c_str()); // PROFILE_OUTPUT(debug_out_path("discover_vertical_shells-profile.txt").c_str());
} }
/* This method applies bridge flow to the first internal solid layer above // This method applies bridge flow to the first internal solid layer above sparse infill.
sparse infill */
void PrintObject::bridge_over_infill() void PrintObject::bridge_over_infill()
{ {
BOOST_LOG_TRIVIAL(info) << "Bridge over infill..." << log_memory_info(); BOOST_LOG_TRIVIAL(info) << "Bridge over infill..." << log_memory_info();
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) { std::vector<int> sparse_infill_regions;
const PrintRegion &region = this->printing_region(region_id); for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id)
if (const PrintRegion &region = this->printing_region(region_id); region.config().sparse_infill_density.value < 100)
sparse_infill_regions.emplace_back(region_id);
if (this->layer_count() < 2 || sparse_infill_regions.empty())
return;
// skip bridging in case there are no voids // Collect sum of all internal (sparse infill) regions, because
if (region.config().sparse_infill_density.value == 100) // 1) layerm->fill_surfaces.will be modified in parallel.
continue; // 2) the parallel loop works on a sum of surfaces over regions anyways, thus collecting the sparse infill surfaces
// up front is an optimization.
std::vector<Polygons> internals;
internals.reserve(this->layer_count());
for (Layer *layer : m_layers) {
Polygons sum;
for (const LayerRegion *layerm : layer->m_regions)
layerm->fill_surfaces.filter_by_type(stInternal, &sum);
internals.emplace_back(std::move(sum));
}
for (LayerPtrs::iterator layer_it = m_layers.begin(); layer_it != m_layers.end(); ++ layer_it) { // Process all regions and layers in parallel.
// skip first layer tbb::parallel_for(tbb::blocked_range<size_t>(0, sparse_infill_regions.size() * (this->layer_count() - 1), sparse_infill_regions.size()),
if (layer_it == m_layers.begin()) [this, &sparse_infill_regions, &internals]
continue; (const tbb::blocked_range<size_t> &range) {
for (size_t task_id = range.begin(); task_id != range.end(); ++ task_id) {
Layer *layer = *layer_it; const size_t layer_id = (task_id / sparse_infill_regions.size()) + 1;
const size_t region_id = sparse_infill_regions[task_id % sparse_infill_regions.size()];
Layer *layer = this->get_layer(layer_id);
LayerRegion *layerm = layer->m_regions[region_id]; LayerRegion *layerm = layer->m_regions[region_id];
const PrintObjectConfig& object_config = layer->object()->config(); const PrintObjectConfig& object_config = layer->object()->config();
//BBS: enable thick bridge for internal bridge only //BBS: enable thick bridge for internal bridge only
Flow bridge_flow = layerm->bridging_flow(frSolidInfill, true); Flow bridge_flow = layerm->bridging_flow(frSolidInfill, true);
// extract the stInternalSolid surfaces that might be transformed into bridges // Extract the stInternalSolid surfaces that might be transformed into bridges.
Polygons internal_solid; ExPolygons internal_solid;
layerm->fill_surfaces.filter_by_type(stInternalSolid, &internal_solid); layerm->fill_surfaces.remove_type(stInternalSolid, &internal_solid);
if (internal_solid.empty())
// No internal solid -> no new bridges for this layer region.
continue;
// check whether the lower area is deep enough for absorbing the extra flow // check whether the lower area is deep enough for absorbing the extra flow
// (for obvious physical reasons but also for preventing the bridge extrudates // (for obvious physical reasons but also for preventing the bridge extrudates
// from overflowing in 3D preview) // from overflowing in 3D preview)
ExPolygons to_bridge; ExPolygons to_bridge;
{ {
Polygons to_bridge_pp = internal_solid; Polygons to_bridge_pp = to_polygons(internal_solid);
// Iterate through lower layers spanned by bridge_flow.
// iterate through lower layers spanned by bridge_flow
double bottom_z = layer->print_z - bridge_flow.height() - EPSILON; double bottom_z = layer->print_z - bridge_flow.height() - EPSILON;
for (int i = int(layer_it - m_layers.begin()) - 1; i >= 0; --i) { for (auto i = int(layer_id) - 1; i >= 0; -- i) {
const Layer* lower_layer = m_layers[i]; // Stop iterating if layer is lower than bottom_z.
if (m_layers[i]->print_z < bottom_z)
// stop iterating if layer is lower than bottom_z break;
if (lower_layer->print_z < bottom_z) break; // Intersect lower sparse infills with the candidate solid surfaces.
to_bridge_pp = intersection(to_bridge_pp, internals[i]);
// iterate through regions and collect internal surfaces
Polygons lower_internal;
for (LayerRegion *lower_layerm : lower_layer->m_regions)
lower_layerm->fill_surfaces.filter_by_type(stInternal, &lower_internal);
// intersect such lower internal surfaces with the candidate solid surfaces
to_bridge_pp = intersection(to_bridge_pp, lower_internal);
} }
// BBS: expand to make avoid gap between bridge and inner wall // BBS: expand to make avoid gap between bridge and inner wall
to_bridge_pp = expand(to_bridge_pp, bridge_flow.scaled_width()); to_bridge_pp = expand(to_bridge_pp, bridge_flow.scaled_width());
to_bridge_pp = intersection(to_bridge_pp, internal_solid); to_bridge_pp = intersection(to_bridge_pp, to_polygons(internal_solid));
// there's no point in bridging too thin/short regions // there's no point in bridging too thin/short regions
//FIXME Vojtech: The offset2 function is not a geometric offset, //FIXME Vojtech: The offset2 function is not a geometric offset,
@ -1793,7 +1802,12 @@ void PrintObject::bridge_over_infill()
to_bridge_pp = opening(to_bridge_pp, min_width); to_bridge_pp = opening(to_bridge_pp, min_width);
} }
if (to_bridge_pp.empty()) continue; if (to_bridge_pp.empty()) {
// Restore internal_solid surfaces.
for (ExPolygon &ex : internal_solid)
layerm->fill_surfaces.surfaces.push_back(Surface(stInternalSolid, std::move(ex)));
continue;
}
// convert into ExPolygons // convert into ExPolygons
to_bridge = union_ex(to_bridge_pp); to_bridge = union_ex(to_bridge_pp);
@ -1807,7 +1821,6 @@ void PrintObject::bridge_over_infill()
ExPolygons not_to_bridge = diff_ex(internal_solid, to_bridge, ApplySafetyOffset::Yes); ExPolygons not_to_bridge = diff_ex(internal_solid, to_bridge, ApplySafetyOffset::Yes);
to_bridge = intersection_ex(to_bridge, internal_solid, ApplySafetyOffset::Yes); to_bridge = intersection_ex(to_bridge, internal_solid, ApplySafetyOffset::Yes);
// build the new collection of fill_surfaces // build the new collection of fill_surfaces
layerm->fill_surfaces.remove_type(stInternalSolid);
for (ExPolygon &ex : to_bridge) { for (ExPolygon &ex : to_bridge) {
layerm->fill_surfaces.surfaces.push_back(Surface(stInternalBridge, ex)); layerm->fill_surfaces.surfaces.push_back(Surface(stInternalBridge, ex));
// BBS: detect angle for internal bridge infill // BBS: detect angle for internal bridge infill
@ -1825,8 +1838,8 @@ void PrintObject::bridge_over_infill()
float internal_loop_thickness = object_config.internal_bridge_support_thickness.value; float internal_loop_thickness = object_config.internal_bridge_support_thickness.value;
double bottom_z = layer->print_z - layer->height - internal_loop_thickness + EPSILON; double bottom_z = layer->print_z - layer->height - internal_loop_thickness + EPSILON;
//BBS: lighting infill doesn't support this feature. Don't need to add loop when infill density is high than 50% //BBS: lighting infill doesn't support this feature. Don't need to add loop when infill density is high than 50%
if (region.config().sparse_infill_pattern != InfillPattern::ipLightning && region.config().sparse_infill_density.value < 50) if (layerm->region().config().sparse_infill_pattern != InfillPattern::ipLightning && layerm->region().config().sparse_infill_density.value < 50)
for (int i = int(layer_it - m_layers.begin()) - 1; i >= 0; --i) { for (int i = layer_id - 1; i >= 0; --i) {
const Layer* lower_layer = m_layers[i]; const Layer* lower_layer = m_layers[i];
if (lower_layer->print_z < bottom_z) break; if (lower_layer->print_z < bottom_z) break;
@ -1893,7 +1906,7 @@ void PrintObject::bridge_over_infill()
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
m_print->throw_if_canceled(); m_print->throw_if_canceled();
} }
} });
} }
static void clamp_exturder_to_default(ConfigOptionInt &opt, size_t num_extruders) static void clamp_exturder_to_default(ConfigOptionInt &opt, size_t num_extruders)

View file

@ -65,7 +65,7 @@ SurfacesPtr SurfaceCollection::filter_by_types(const SurfaceType *types, int nty
return ss; return ss;
} }
void SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons) void SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons) const
{ {
for (const Surface &surface : this->surfaces) for (const Surface &surface : this->surfaces)
if (surface.surface_type == type) if (surface.surface_type == type)
@ -121,6 +121,22 @@ void SurfaceCollection::remove_type(const SurfaceType type)
surfaces.erase(surfaces.begin() + j, surfaces.end()); surfaces.erase(surfaces.begin() + j, surfaces.end());
} }
void SurfaceCollection::remove_type(const SurfaceType type, ExPolygons *polygons)
{
size_t j = 0;
for (size_t i = 0; i < surfaces.size(); ++ i) {
if (Surface &surface = surfaces[i]; surface.surface_type == type) {
polygons->emplace_back(std::move(surface.expolygon));
} else {
if (j < i)
std::swap(surfaces[i], surfaces[j]);
++ j;
}
}
if (j < surfaces.size())
surfaces.erase(surfaces.begin() + j, surfaces.end());
}
void SurfaceCollection::remove_types(const SurfaceType *types, int ntypes) void SurfaceCollection::remove_types(const SurfaceType *types, int ntypes)
{ {
size_t j = 0; size_t j = 0;

View file

@ -32,7 +32,8 @@ public:
void keep_types(const SurfaceType *types, int ntypes); void keep_types(const SurfaceType *types, int ntypes);
void remove_type(const SurfaceType type); void remove_type(const SurfaceType type);
void remove_types(const SurfaceType *types, int ntypes); void remove_types(const SurfaceType *types, int ntypes);
void filter_by_type(SurfaceType type, Polygons* polygons); void filter_by_type(SurfaceType type, Polygons* polygons) const;
void remove_type(const SurfaceType type, ExPolygons *polygons);
void set_type(SurfaceType type) { void set_type(SurfaceType type) {
for (Surface &surface : this->surfaces) for (Surface &surface : this->surfaces)
surface.surface_type = type; surface.surface_type = type;