WIP Reworking of "ensure vertical wall thickness".
1) Flipped the order of "discover_vertical_shells" and "process_external_surfaces", now the external surfaces are expanded after "discover_vertical_shells" aka "ensure vertical wall thickness" is solved. 2) Reworked LayerRegion::process_external_surfaces() to only expand into "ensure vertical wall thickness" regions, also the expansion is done in small steps to avoid overflowing into neighbor regions. also: Utility functions reserve_more(), reserve_power_of_2(), reserve_more_power_of_2() Various SurfaceCollecion::filter_xxx() modified to accept an initializer list of surface types. New bridges detector refactored to accept overhang boundaries. BoundingBoxWrapper was moved from RetractCrossingPerimeters to AABBTreeIndirect.
This commit is contained in:
parent
fb85baf889
commit
fde0d68c40
12 changed files with 841 additions and 308 deletions
src/libslic3r
|
@ -260,6 +260,22 @@ void PrintObject::prepare_infill()
|
|||
m_print->throw_if_canceled();
|
||||
}
|
||||
|
||||
|
||||
// Add solid fills to ensure the shell vertical thickness.
|
||||
this->discover_vertical_shells();
|
||||
m_print->throw_if_canceled();
|
||||
|
||||
// Debugging output.
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
for (const Layer *layer : m_layers) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
layerm->export_region_slices_to_svg_debug("3_discover_vertical_shells-final");
|
||||
layerm->export_region_fill_surfaces_to_svg_debug("3_discover_vertical_shells-final");
|
||||
} // for each layer
|
||||
} // for each region
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
||||
// this will detect bridges and reverse bridges
|
||||
// and rearrange top/bottom/internal surfaces
|
||||
// It produces enlarged overlapping bridging areas.
|
||||
|
@ -272,17 +288,13 @@ void PrintObject::prepare_infill()
|
|||
this->process_external_surfaces();
|
||||
m_print->throw_if_canceled();
|
||||
|
||||
// Add solid fills to ensure the shell vertical thickness.
|
||||
this->discover_vertical_shells();
|
||||
m_print->throw_if_canceled();
|
||||
|
||||
// Debugging output.
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
for (const Layer *layer : m_layers) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
layerm->export_region_slices_to_svg_debug("6_discover_vertical_shells-final");
|
||||
layerm->export_region_fill_surfaces_to_svg_debug("6_discover_vertical_shells-final");
|
||||
layerm->export_region_slices_to_svg_debug("3_process_external_surfaces-final");
|
||||
layerm->export_region_fill_surfaces_to_svg_debug("3_process_external_surfaces-final");
|
||||
} // for each layer
|
||||
} // for each region
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
@ -1042,7 +1054,7 @@ void PrintObject::process_external_surfaces()
|
|||
if (has_voids && m_layers.size() > 1) {
|
||||
// All but stInternal fill surfaces will get expanded and possibly trimmed.
|
||||
std::vector<unsigned char> layer_expansions_and_voids(m_layers.size(), false);
|
||||
for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++ layer_idx) {
|
||||
for (size_t layer_idx = 1; layer_idx < m_layers.size(); ++ layer_idx) {
|
||||
const Layer *layer = m_layers[layer_idx];
|
||||
bool expansions = false;
|
||||
bool voids = false;
|
||||
|
@ -1068,6 +1080,8 @@ void PrintObject::process_external_surfaces()
|
|||
[this, &surfaces_covered, &layer_expansions_and_voids, unsupported_width](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
|
||||
if (layer_expansions_and_voids[layer_idx + 1]) {
|
||||
// Layer above is partially filled with solid infill (top, bottom, bridging...),
|
||||
// while some sparse inill regions are empty (0% infill).
|
||||
m_print->throw_if_canceled();
|
||||
Polygons voids;
|
||||
for (const LayerRegion *layerm : m_layers[layer_idx]->regions()) {
|
||||
|
@ -1093,7 +1107,9 @@ void PrintObject::process_external_surfaces()
|
|||
m_print->throw_if_canceled();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "Processing external surface, layer" << m_layers[layer_idx]->print_z;
|
||||
m_layers[layer_idx]->get_region(int(region_id))->process_external_surfaces(
|
||||
// lower layer
|
||||
(layer_idx == 0) ? nullptr : m_layers[layer_idx - 1],
|
||||
// lower layer polygons with density > 0%
|
||||
(layer_idx == 0 || surfaces_covered.empty() || surfaces_covered[layer_idx - 1].empty()) ? nullptr : &surfaces_covered[layer_idx - 1]);
|
||||
}
|
||||
}
|
||||
|
@ -1152,7 +1168,7 @@ void PrintObject::discover_vertical_shells()
|
|||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, num_layers, grain_size),
|
||||
[this, &cache_top_botom_regions](const tbb::blocked_range<size_t>& range) {
|
||||
const SurfaceType surfaces_bottom[2] = { stBottom, stBottomBridge };
|
||||
const std::initializer_list<SurfaceType> surfaces_bottom { stBottom, stBottomBridge };
|
||||
const size_t num_regions = this->num_printing_regions();
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
m_print->throw_if_canceled();
|
||||
|
@ -1172,8 +1188,8 @@ void PrintObject::discover_vertical_shells()
|
|||
append(cache.top_surfaces, offset(layerm.slices().filter_by_type(stTop), min_perimeter_infill_spacing));
|
||||
append(cache.top_surfaces, offset(layerm.fill_surfaces().filter_by_type(stTop), min_perimeter_infill_spacing));
|
||||
// Bottom surfaces.
|
||||
append(cache.bottom_surfaces, offset(layerm.slices().filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing));
|
||||
append(cache.bottom_surfaces, offset(layerm.fill_surfaces().filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing));
|
||||
append(cache.bottom_surfaces, offset(layerm.slices().filter_by_types(surfaces_bottom), min_perimeter_infill_spacing));
|
||||
append(cache.bottom_surfaces, offset(layerm.fill_surfaces().filter_by_types(surfaces_bottom), min_perimeter_infill_spacing));
|
||||
// Calculate the maximum perimeter offset as if the slice was extruded with a single extruder only.
|
||||
// First find the maxium number of perimeters per region slice.
|
||||
unsigned int perimeters = 0;
|
||||
|
@ -1233,7 +1249,7 @@ void PrintObject::discover_vertical_shells()
|
|||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, num_layers, grain_size),
|
||||
[this, region_id, &cache_top_botom_regions](const tbb::blocked_range<size_t>& range) {
|
||||
const SurfaceType surfaces_bottom[2] = { stBottom, stBottomBridge };
|
||||
const std::initializer_list<SurfaceType> surfaces_bottom { stBottom, stBottomBridge };
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
m_print->throw_if_canceled();
|
||||
Layer &layer = *m_layers[idx_layer];
|
||||
|
@ -1244,8 +1260,8 @@ void PrintObject::discover_vertical_shells()
|
|||
cache.top_surfaces = offset(layerm.slices().filter_by_type(stTop), min_perimeter_infill_spacing);
|
||||
append(cache.top_surfaces, offset(layerm.fill_surfaces().filter_by_type(stTop), min_perimeter_infill_spacing));
|
||||
// Bottom surfaces.
|
||||
cache.bottom_surfaces = offset(layerm.slices().filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing);
|
||||
append(cache.bottom_surfaces, offset(layerm.fill_surfaces().filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing));
|
||||
cache.bottom_surfaces = offset(layerm.slices().filter_by_types(surfaces_bottom), min_perimeter_infill_spacing);
|
||||
append(cache.bottom_surfaces, offset(layerm.fill_surfaces().filter_by_types(surfaces_bottom), min_perimeter_infill_spacing));
|
||||
// Holes over all regions. Only collect them once, they are valid for all region_id iterations.
|
||||
if (cache.holes.empty()) {
|
||||
for (size_t region_id = 0; region_id < layer.regions().size(); ++ region_id)
|
||||
|
@ -1275,8 +1291,8 @@ void PrintObject::discover_vertical_shells()
|
|||
const PrintRegionConfig ®ion_config = layerm->region().config();
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
layerm->export_region_slices_to_svg_debug("4_discover_vertical_shells-initial");
|
||||
layerm->export_region_fill_surfaces_to_svg_debug("4_discover_vertical_shells-initial");
|
||||
layerm->export_region_slices_to_svg_debug("3_discover_vertical_shells-initial");
|
||||
layerm->export_region_fill_surfaces_to_svg_debug("3_discover_vertical_shells-initial");
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
||||
Flow solid_infill_flow = layerm->flow(frSolidInfill);
|
||||
|
@ -1405,8 +1421,7 @@ void PrintObject::discover_vertical_shells()
|
|||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
||||
// Trim the shells region by the internal & internal void surfaces.
|
||||
const SurfaceType surfaceTypesInternal[] = { stInternal, stInternalVoid, stInternalSolid };
|
||||
const Polygons polygonsInternal = to_polygons(layerm->fill_surfaces().filter_by_types(surfaceTypesInternal, 3));
|
||||
const Polygons polygonsInternal = to_polygons(layerm->fill_surfaces().filter_by_types({ stInternal, stInternalVoid, stInternalSolid }));
|
||||
shell = intersection(shell, polygonsInternal, ApplySafetyOffset::Yes);
|
||||
polygons_append(shell, diff(polygonsInternal, holes));
|
||||
if (shell.empty())
|
||||
|
@ -1472,8 +1487,7 @@ void PrintObject::discover_vertical_shells()
|
|||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
||||
// Assign resulting internal surfaces to layer.
|
||||
const SurfaceType surfaceTypesKeep[] = { stTop, stBottom, stBottomBridge };
|
||||
layerm->m_fill_surfaces.keep_types(surfaceTypesKeep, sizeof(surfaceTypesKeep)/sizeof(SurfaceType));
|
||||
layerm->m_fill_surfaces.keep_types({ stTop, stBottom, stBottomBridge });
|
||||
layerm->m_fill_surfaces.append(new_internal, stInternal);
|
||||
layerm->m_fill_surfaces.append(new_internal_void, stInternalVoid);
|
||||
layerm->m_fill_surfaces.append(new_internal_solid, stInternalSolid);
|
||||
|
@ -1485,8 +1499,8 @@ void PrintObject::discover_vertical_shells()
|
|||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++idx_layer) {
|
||||
LayerRegion *layerm = m_layers[idx_layer]->get_region(region_id);
|
||||
layerm->export_region_slices_to_svg_debug("4_discover_vertical_shells-final");
|
||||
layerm->export_region_fill_surfaces_to_svg_debug("4_discover_vertical_shells-final");
|
||||
layerm->export_region_slices_to_svg_debug("3_discover_vertical_shells-final");
|
||||
layerm->export_region_fill_surfaces_to_svg_debug("3_discover_vertical_shells-final");
|
||||
}
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
} // for each region
|
||||
|
@ -1870,12 +1884,11 @@ void PrintObject::clip_fill_surfaces()
|
|||
for (LayerRegion *layerm : lower_layer->m_regions) {
|
||||
if (layerm->region().config().fill_density.value == 0)
|
||||
continue;
|
||||
SurfaceType internal_surface_types[] = { stInternal, stInternalVoid };
|
||||
Polygons internal;
|
||||
for (Surface &surface : layerm->m_fill_surfaces.surfaces)
|
||||
if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
|
||||
polygons_append(internal, std::move(surface.expolygon));
|
||||
layerm->m_fill_surfaces.remove_types(internal_surface_types, 2);
|
||||
layerm->m_fill_surfaces.remove_types({ stInternal, stInternalVoid });
|
||||
layerm->m_fill_surfaces.append(intersection_ex(internal, upper_internal, ApplySafetyOffset::Yes), stInternal);
|
||||
layerm->m_fill_surfaces.append(diff_ex (internal, upper_internal, ApplySafetyOffset::Yes), stInternalVoid);
|
||||
// If there are voids it means that our internal infill is not adjacent to
|
||||
|
@ -2058,8 +2071,7 @@ void PrintObject::discover_horizontal_shells()
|
|||
neighbor_layerm->m_fill_surfaces.append(internal, stInternal);
|
||||
polygons_append(polygons_internal, to_polygons(std::move(internal)));
|
||||
// assign top and bottom surfaces to layer
|
||||
SurfaceType surface_types_solid[] = { stTop, stBottom, stBottomBridge };
|
||||
backup.keep_types(surface_types_solid, 3);
|
||||
backup.keep_types({ stTop, stBottom, stBottomBridge });
|
||||
std::vector<SurfacesPtr> top_bottom_groups;
|
||||
backup.group(&top_bottom_groups);
|
||||
for (SurfacesPtr &group : top_bottom_groups)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue