WIP: Splitting the number of top / bottom support interface layers.

If the new support_material_bottom_interface_layers is left at default -1,
then support_material_interface_layers is used for both top and bottom
interface layers.
If support_material_interface_layers == 0, then neither top nor bottom
interface layers are being extruded.
This commit is contained in:
Vojtech Bubnik 2021-03-09 15:29:13 +01:00
parent adcbe4347c
commit 00db3dc419
8 changed files with 81 additions and 49 deletions

View file

@ -2720,17 +2720,23 @@ std::pair<PrintObjectSupportMaterial::MyLayersPtr, PrintObjectSupportMaterial::M
m_object_config->support_material_interface_extruder.value > 0 && m_print_config->filament_soluble.get_at(m_object_config->support_material_interface_extruder.value - 1) &&
// Base extruder: Either "print with active extruder" not soluble.
(m_object_config->support_material_extruder.value == 0 || ! m_print_config->filament_soluble.get_at(m_object_config->support_material_extruder.value - 1));
int num_interface_layers = m_object_config->support_material_interface_layers.value;
int num_base_interface_layers = soluble_interface_non_soluble_base ? std::min(num_interface_layers / 2, 2) : 0;
int num_interface_layers_top = m_object_config->support_material_interface_layers;
int num_interface_layers_bottom = m_object_config->support_material_bottom_interface_layers;
if (num_interface_layers_bottom < 0)
num_interface_layers_bottom = num_interface_layers_top;
int num_base_interface_layers_top = soluble_interface_non_soluble_base ? std::min(num_interface_layers_top / 2, 2) : 0;
int num_base_interface_layers_bottom = soluble_interface_non_soluble_base ? std::min(num_interface_layers_bottom / 2, 2) : 0;
if (! intermediate_layers.empty() && num_interface_layers > 1) {
if (! intermediate_layers.empty() && (num_interface_layers_top > 1 || num_interface_layers_bottom > 1)) {
// For all intermediate layers, collect top contact surfaces, which are not further than support_material_interface_layers.
BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_interface_layers() in parallel - start";
// Since the intermediate layer index starts at zero the number of interface layer needs to be reduced by 1.
-- num_interface_layers;
int num_interface_layers_only = num_interface_layers - num_base_interface_layers;
-- num_interface_layers_top;
-- num_interface_layers_bottom;
int num_interface_layers_only_top = num_interface_layers_top - num_base_interface_layers_top;
int num_interface_layers_only_bottom = num_interface_layers_bottom - num_base_interface_layers_bottom;
interface_layers.assign(intermediate_layers.size(), nullptr);
if (num_base_interface_layers)
if (num_base_interface_layers_top || num_base_interface_layers_bottom)
base_interface_layers.assign(intermediate_layers.size(), nullptr);
tbb::spin_mutex layer_storage_mutex;
// Insert a new layer into base_interface_layers, if intersection with base exists.
@ -2754,7 +2760,8 @@ std::pair<PrintObjectSupportMaterial::MyLayersPtr, PrintObjectSupportMaterial::M
return &layer_new;
};
tbb::parallel_for(tbb::blocked_range<int>(0, int(intermediate_layers.size())),
[&bottom_contacts, &top_contacts, &intermediate_layers, &insert_layer, num_interface_layers, num_base_interface_layers, num_interface_layers_only,
[&bottom_contacts, &top_contacts, &intermediate_layers, &insert_layer,
num_interface_layers_top, num_interface_layers_bottom, num_base_interface_layers_top, num_base_interface_layers_bottom, num_interface_layers_only_top, num_interface_layers_only_bottom,
&interface_layers, &base_interface_layers](const tbb::blocked_range<int>& range) {
// Gather the top / bottom contact layers intersecting with num_interface_layers resp. num_interface_layers_only intermediate layers above / below
// this intermediate layer.
@ -2765,45 +2772,51 @@ std::pair<PrintObjectSupportMaterial::MyLayersPtr, PrintObjectSupportMaterial::M
auto num_intermediate = int(intermediate_layers.size());
for (int idx_intermediate_layer = range.begin(); idx_intermediate_layer < range.end(); ++ idx_intermediate_layer) {
MyLayer &intermediate_layer = *intermediate_layers[idx_intermediate_layer];
// Top / bottom Z coordinate of a slab, over which we are collecting the top / bottom contact surfaces
coordf_t top_z = intermediate_layers[std::min(num_intermediate - 1, idx_intermediate_layer + num_interface_layers - 1)]->print_z;
coordf_t top_inteface_z = std::numeric_limits<coordf_t>::max();
coordf_t bottom_z = intermediate_layers[std::max(0, idx_intermediate_layer - num_interface_layers + 1)]->bottom_z;
coordf_t bottom_interface_z = - std::numeric_limits<coordf_t>::max();
if (num_base_interface_layers > 0) {
// Some base interface layers will be generated.
if (num_interface_layers_only == 0)
// Only base interface layers to generate.
std::swap(top_inteface_z, bottom_interface_z);
else {
top_inteface_z = intermediate_layers[std::min(num_intermediate - 1, idx_intermediate_layer + num_interface_layers_only - 1)]->print_z;
bottom_interface_z = intermediate_layers[std::max(0, idx_intermediate_layer - num_interface_layers_only)]->bottom_z;
}
}
// Move idx_top_contact_first up until above the current print_z.
idx_top_contact_first = idx_higher_or_equal(top_contacts, idx_top_contact_first, [&intermediate_layer](const MyLayer *layer){ return layer->print_z >= intermediate_layer.print_z; }); // - EPSILON
// Collect the top contact areas above this intermediate layer, below top_z.
Polygons polygons_top_contact_projected_interface;
Polygons polygons_top_contact_projected_base;
for (int idx_top_contact = idx_top_contact_first; idx_top_contact < int(top_contacts.size()); ++ idx_top_contact) {
const MyLayer &top_contact_layer = *top_contacts[idx_top_contact];
//FIXME maybe this adds one interface layer in excess?
if (top_contact_layer.bottom_z - EPSILON > top_z)
break;
polygons_append(top_contact_layer.bottom_z - EPSILON > top_inteface_z ? polygons_top_contact_projected_base : polygons_top_contact_projected_interface, top_contact_layer.polygons);
}
// Move idx_bottom_contact_first up until touching bottom_z.
idx_bottom_contact_first = idx_higher_or_equal(bottom_contacts, idx_bottom_contact_first, [bottom_z](const MyLayer *layer){ return layer->print_z >= bottom_z - EPSILON; });
// Collect the top contact areas above this intermediate layer, below top_z.
Polygons polygons_bottom_contact_projected_interface;
Polygons polygons_bottom_contact_projected_base;
for (int idx_bottom_contact = idx_bottom_contact_first; idx_bottom_contact < int(bottom_contacts.size()); ++ idx_bottom_contact) {
const MyLayer &bottom_contact_layer = *bottom_contacts[idx_bottom_contact];
if (bottom_contact_layer.print_z - EPSILON > intermediate_layer.bottom_z)
break;
polygons_append(bottom_contact_layer.print_z - EPSILON > bottom_interface_z ? polygons_bottom_contact_projected_interface : polygons_bottom_contact_projected_base, bottom_contact_layer.polygons);
if (num_interface_layers_top > -1) {
// Top Z coordinate of a slab, over which we are collecting the top / bottom contact surfaces
coordf_t top_z = intermediate_layers[std::min(num_intermediate - 1, idx_intermediate_layer + num_interface_layers_top - 1)]->print_z;
coordf_t top_inteface_z = std::numeric_limits<coordf_t>::max();
if (num_base_interface_layers_top > 0)
// Some top base interface layers will be generated.
top_inteface_z = num_interface_layers_only_top == 0 ?
// Only base interface layers to generate.
- std::numeric_limits<coordf_t>::max() :
intermediate_layers[std::min(num_intermediate - 1, idx_intermediate_layer + num_interface_layers_only_top - 1)]->print_z;
// Move idx_top_contact_first up until above the current print_z.
idx_top_contact_first = idx_higher_or_equal(top_contacts, idx_top_contact_first, [&intermediate_layer](const MyLayer *layer){ return layer->print_z >= intermediate_layer.print_z; }); // - EPSILON
// Collect the top contact areas above this intermediate layer, below top_z.
for (int idx_top_contact = idx_top_contact_first; idx_top_contact < int(top_contacts.size()); ++ idx_top_contact) {
const MyLayer &top_contact_layer = *top_contacts[idx_top_contact];
//FIXME maybe this adds one interface layer in excess?
if (top_contact_layer.bottom_z - EPSILON > top_z)
break;
polygons_append(top_contact_layer.bottom_z - EPSILON > top_inteface_z ? polygons_top_contact_projected_base : polygons_top_contact_projected_interface, top_contact_layer.polygons);
}
}
if (num_interface_layers_bottom > -1) {
// Bottom Z coordinate of a slab, over which we are collecting the top / bottom contact surfaces
coordf_t bottom_z = intermediate_layers[std::max(0, idx_intermediate_layer - num_interface_layers_bottom + 1)]->bottom_z;
coordf_t bottom_interface_z = - std::numeric_limits<coordf_t>::max();
if (num_base_interface_layers_bottom > 0)
// Some bottom base interface layers will be generated.
bottom_interface_z = num_interface_layers_only_bottom == 0 ?
// Only base interface layers to generate.
std::numeric_limits<coordf_t>::max() :
intermediate_layers[std::max(0, idx_intermediate_layer - num_interface_layers_only_bottom)]->bottom_z;
// Move idx_bottom_contact_first up until touching bottom_z.
idx_bottom_contact_first = idx_higher_or_equal(bottom_contacts, idx_bottom_contact_first, [bottom_z](const MyLayer *layer){ return layer->print_z >= bottom_z - EPSILON; });
// Collect the top contact areas above this intermediate layer, below top_z.
for (int idx_bottom_contact = idx_bottom_contact_first; idx_bottom_contact < int(bottom_contacts.size()); ++ idx_bottom_contact) {
const MyLayer &bottom_contact_layer = *bottom_contacts[idx_bottom_contact];
if (bottom_contact_layer.print_z - EPSILON > intermediate_layer.bottom_z)
break;
polygons_append(bottom_contact_layer.print_z - EPSILON > bottom_interface_z ? polygons_bottom_contact_projected_interface : polygons_bottom_contact_projected_base, bottom_contact_layer.polygons);
}
}
MyLayer *interface_layer = nullptr;
if (! polygons_bottom_contact_projected_interface.empty() || ! polygons_top_contact_projected_interface.empty()) {
interface_layer = insert_layer(
@ -3712,10 +3725,6 @@ void PrintObjectSupportMaterial::generate_toolpaths(
base_layer.merge(std::move(top_contact_layer));
else if (base_layer.empty() && !top_contact_layer.empty() && !top_contact_layer.layer->bridging)
std::swap(base_layer, top_contact_layer);
if (base_layer.could_merge(bottom_contact_layer))
base_layer.merge(std::move(bottom_contact_layer));
else if (base_layer.empty() && !bottom_contact_layer.empty() && !bottom_contact_layer.layer->bridging)
std::swap(base_layer, bottom_contact_layer);
}
} else {
loop_interface_processor.generate(top_contact_layer, m_support_material_interface_flow);
@ -3725,6 +3734,12 @@ void PrintObjectSupportMaterial::generate_toolpaths(
if (top_contact_layer.could_merge(interface_layer))
top_contact_layer.merge(std::move(interface_layer));
}
if ((m_object_config->support_material_interface_layers == 0 || m_object_config->support_material_bottom_interface_layers == 0) && m_can_merge_support_regions) {
if (base_layer.could_merge(bottom_contact_layer))
base_layer.merge(std::move(bottom_contact_layer));
else if (base_layer.empty() && !bottom_contact_layer.empty() && !bottom_contact_layer.layer->bridging)
std::swap(base_layer, bottom_contact_layer);
}
#if 0
if ( ! interface_layer.empty() && ! base_layer.empty()) {