Parallelized PrintObject::bridge_over_infill()
This commit is contained in:
parent
7949ea9544
commit
14e0cd0e96
@ -1441,56 +1441,64 @@ 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 ®ion = this->printing_region(region_id);
|
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id)
|
||||||
|
if (const PrintRegion ®ion = this->printing_region(region_id); region.config().fill_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().fill_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];
|
||||||
Flow bridge_flow = layerm->bridging_flow(frSolidInfill);
|
Flow bridge_flow = layerm->bridging_flow(frSolidInfill);
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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,
|
||||||
// therefore it may create 1) gaps, and 2) sharp corners, which are outside the original contour.
|
// therefore it may create 1) gaps, and 2) sharp corners, which are outside the original contour.
|
||||||
@ -1500,8 +1508,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);
|
||||||
}
|
}
|
||||||
@ -1514,11 +1526,10 @@ 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, std::move(ex)));
|
||||||
for (ExPolygon &ex : not_to_bridge)
|
for (ExPolygon &ex : not_to_bridge)
|
||||||
layerm->fill_surfaces.surfaces.push_back(Surface(stInternalSolid, ex));
|
layerm->fill_surfaces.surfaces.push_back(Surface(stInternalSolid, std::move(ex)));
|
||||||
/*
|
/*
|
||||||
# exclude infill from the layers below if needed
|
# exclude infill from the layers below if needed
|
||||||
# see discussion at https://github.com/alexrj/Slic3r/issues/240
|
# see discussion at https://github.com/alexrj/Slic3r/issues/240
|
||||||
@ -1552,14 +1563,13 @@ void PrintObject::bridge_over_infill()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
layerm->export_region_slices_to_svg_debug("7_bridge_over_infill");
|
layerm->export_region_slices_to_svg_debug("7_bridge_over_infill");
|
||||||
layerm->export_region_fill_surfaces_to_svg_debug("7_bridge_over_infill");
|
layerm->export_region_fill_surfaces_to_svg_debug("7_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)
|
||||||
|
@ -121,12 +121,12 @@ 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, Polygons *polygons)
|
void SurfaceCollection::remove_type(const SurfaceType type, ExPolygons *polygons)
|
||||||
{
|
{
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
||||||
if (Surface &surface = surfaces[i]; surface.surface_type == type) {
|
if (Surface &surface = surfaces[i]; surface.surface_type == type) {
|
||||||
polygons_append(*polygons, to_polygons(std::move(surface.expolygon)));
|
polygons->emplace_back(std::move(surface.expolygon));
|
||||||
} else {
|
} else {
|
||||||
if (j < i)
|
if (j < i)
|
||||||
std::swap(surfaces[i], surfaces[j]);
|
std::swap(surfaces[i], surfaces[j]);
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
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) const;
|
void filter_by_type(SurfaceType type, Polygons *polygons) const;
|
||||||
void remove_type(const SurfaceType type, Polygons *polygons);
|
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user