Fixing missing dense raft layers with number of support top interface

layers set to zero.
Fixes #7951, second picture.
This commit is contained in:
Vojtech Bubnik 2023-02-27 17:09:39 +01:00
parent 2098ce9cfa
commit 8354d2b52c
2 changed files with 82 additions and 45 deletions

View File

@ -335,6 +335,7 @@ SupportParameters::SupportParameters(const PrintObject &object)
this->first_layer_flow = Slic3r::support_material_1st_layer_flow(&object, float(slicing_params.first_print_layer_height)); this->first_layer_flow = Slic3r::support_material_1st_layer_flow(&object, float(slicing_params.first_print_layer_height));
this->support_material_flow = Slic3r::support_material_flow(&object, float(slicing_params.layer_height)); this->support_material_flow = Slic3r::support_material_flow(&object, float(slicing_params.layer_height));
this->support_material_interface_flow = Slic3r::support_material_interface_flow(&object, float(slicing_params.layer_height)); this->support_material_interface_flow = Slic3r::support_material_interface_flow(&object, float(slicing_params.layer_height));
this->raft_interface_flow = support_material_interface_flow;
// Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um. // Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um.
this->support_layer_height_min = scaled<coord_t>(0.01); this->support_layer_height_min = scaled<coord_t>(0.01);
@ -377,13 +378,14 @@ SupportParameters::SupportParameters(const PrintObject &object)
this->base_angle = Geometry::deg2rad(float(object_config.support_material_angle.value)); this->base_angle = Geometry::deg2rad(float(object_config.support_material_angle.value));
this->interface_angle = Geometry::deg2rad(float(object_config.support_material_angle.value + 90.)); this->interface_angle = Geometry::deg2rad(float(object_config.support_material_angle.value + 90.));
this->interface_spacing = object_config.support_material_interface_spacing.value + this->support_material_interface_flow.spacing(); double interface_spacing = object_config.support_material_interface_spacing.value + this->support_material_interface_flow.spacing();
this->interface_density = std::min(1., this->support_material_interface_flow.spacing() / this->interface_spacing); this->interface_density = std::min(1., this->support_material_interface_flow.spacing() / interface_spacing);
this->support_spacing = object_config.support_material_spacing.value + this->support_material_flow.spacing(); double raft_interface_spacing = object_config.support_material_interface_spacing.value + this->raft_interface_flow.spacing();
this->support_density = std::min(1., this->support_material_flow.spacing() / this->support_spacing); this->raft_interface_density = std::min(1., this->raft_interface_flow.spacing() / raft_interface_spacing);
double support_spacing = object_config.support_material_spacing.value + this->support_material_flow.spacing();
this->support_density = std::min(1., this->support_material_flow.spacing() / support_spacing);
if (object_config.support_material_interface_layers.value == 0) { if (object_config.support_material_interface_layers.value == 0) {
// No interface layers allowed, print everything with the base support pattern. // No interface layers allowed, print everything with the base support pattern.
this->interface_spacing = this->support_spacing;
this->interface_density = this->support_density; this->interface_density = this->support_density;
} }
@ -393,6 +395,7 @@ SupportParameters::SupportParameters(const PrintObject &object)
support_pattern == smpHoneycomb ? ipHoneycomb : support_pattern == smpHoneycomb ? ipHoneycomb :
this->support_density > 0.95 || this->with_sheath ? ipRectilinear : ipSupportBase; this->support_density > 0.95 || this->with_sheath ? ipRectilinear : ipSupportBase;
this->interface_fill_pattern = (this->interface_density > 0.95 ? ipRectilinear : ipSupportBase); this->interface_fill_pattern = (this->interface_density > 0.95 ? ipRectilinear : ipSupportBase);
this->raft_interface_fill_pattern = this->raft_interface_density > 0.95 ? ipRectilinear : ipSupportBase;
this->contact_fill_pattern = this->contact_fill_pattern =
(object_config.support_material_interface_pattern == smipAuto && slicing_params.soluble_interface) || (object_config.support_material_interface_pattern == smipAuto && slicing_params.soluble_interface) ||
object_config.support_material_interface_pattern == smipConcentric ? object_config.support_material_interface_pattern == smipConcentric ?
@ -4240,11 +4243,11 @@ void generate_support_toolpaths(
for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id) for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id)
{ {
assert(support_layer_id < raft_layers.size()); assert(support_layer_id < raft_layers.size());
SupportLayer &support_layer = *support_layers[support_layer_id]; SupportLayer &support_layer = *support_layers[support_layer_id];
assert(support_layer.support_fills.entities.empty()); assert(support_layer.support_fills.entities.empty());
SupportGeneratorLayer &raft_layer = *raft_layers[support_layer_id]; SupportGeneratorLayer &raft_layer = *raft_layers[support_layer_id];
std::unique_ptr<Fill> filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(support_params.interface_fill_pattern)); std::unique_ptr<Fill> filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(support_params.raft_interface_fill_pattern));
std::unique_ptr<Fill> filler_support = std::unique_ptr<Fill>(Fill::new_from_type(support_params.base_fill_pattern)); std::unique_ptr<Fill> filler_support = std::unique_ptr<Fill>(Fill::new_from_type(support_params.base_fill_pattern));
filler_interface->set_bounding_box(bbox_object); filler_interface->set_bounding_box(bbox_object);
filler_support->set_bounding_box(bbox_object); filler_support->set_bounding_box(bbox_object);
@ -4299,8 +4302,8 @@ void generate_support_toolpaths(
// value that guarantees that all layers are correctly aligned. // value that guarantees that all layers are correctly aligned.
filler->spacing = support_params.support_material_flow.spacing(); filler->spacing = support_params.support_material_flow.spacing();
assert(! raft_layer.bridging); assert(! raft_layer.bridging);
flow = Flow(float(support_params.support_material_interface_flow.width()), float(raft_layer.height), support_params.support_material_flow.nozzle_diameter()); flow = Flow(float(support_params.raft_interface_flow.width()), float(raft_layer.height), support_params.raft_interface_flow.nozzle_diameter());
density = float(support_params.interface_density); density = float(support_params.raft_interface_density);
} else } else
continue; continue;
filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / density)); filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / density));
@ -4343,7 +4346,7 @@ void generate_support_toolpaths(
tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, support_layers.size()), tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, support_layers.size()),
[&config, &support_params, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &base_interface_layers, &layer_caches, &loop_interface_processor, [&config, &support_params, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &base_interface_layers, &layer_caches, &loop_interface_processor,
&bbox_object, &angles, link_max_length_factor] &bbox_object, &angles, n_raft_layers, link_max_length_factor]
(const tbb::blocked_range<size_t>& range) { (const tbb::blocked_range<size_t>& range) {
// Indices of the 1st layer in their respective container at the support layer height. // Indices of the 1st layer in their respective container at the support layer height.
size_t idx_layer_bottom_contact = size_t(-1); size_t idx_layer_bottom_contact = size_t(-1);
@ -4357,6 +4360,11 @@ void generate_support_toolpaths(
auto filler_first_layer_ptr = std::unique_ptr<Fill>(range.begin() == 0 && support_params.contact_fill_pattern != fill_type_first_layer ? Fill::new_from_type(fill_type_first_layer) : nullptr); auto filler_first_layer_ptr = std::unique_ptr<Fill>(range.begin() == 0 && support_params.contact_fill_pattern != fill_type_first_layer ? Fill::new_from_type(fill_type_first_layer) : nullptr);
// Pointer to the 1st layer interface filler. // Pointer to the 1st layer interface filler.
auto filler_first_layer = filler_first_layer_ptr ? filler_first_layer_ptr.get() : filler_interface.get(); auto filler_first_layer = filler_first_layer_ptr ? filler_first_layer_ptr.get() : filler_interface.get();
// Filler for the 1st layer interface, if different from filler_interface.
auto filler_raft_contact_ptr = std::unique_ptr<Fill>(range.begin() == n_raft_layers && config.support_material_interface_layers.value == 0 ?
Fill::new_from_type(support_params.raft_interface_fill_pattern) : nullptr);
// Pointer to the 1st layer interface filler.
auto filler_raft_contact = filler_raft_contact_ptr ? filler_raft_contact_ptr.get() : filler_interface.get();
// Filler for the base interface (to be used for soluble interface / non soluble base, to produce non soluble interface layer below soluble interface layer). // Filler for the base interface (to be used for soluble interface / non soluble base, to produce non soluble interface layer below soluble interface layer).
auto filler_base_interface = std::unique_ptr<Fill>(base_interface_layers.empty() ? nullptr : auto filler_base_interface = std::unique_ptr<Fill>(base_interface_layers.empty() ? nullptr :
Fill::new_from_type(support_params.interface_density > 0.95 || support_params.with_sheath ? ipRectilinear : ipSupportBase)); Fill::new_from_type(support_params.interface_density > 0.95 || support_params.with_sheath ? ipRectilinear : ipSupportBase));
@ -4364,6 +4372,8 @@ void generate_support_toolpaths(
filler_interface->set_bounding_box(bbox_object); filler_interface->set_bounding_box(bbox_object);
if (filler_first_layer_ptr) if (filler_first_layer_ptr)
filler_first_layer_ptr->set_bounding_box(bbox_object); filler_first_layer_ptr->set_bounding_box(bbox_object);
if (filler_raft_contact_ptr)
filler_raft_contact_ptr->set_bounding_box(bbox_object);
if (filler_base_interface) if (filler_base_interface)
filler_base_interface->set_bounding_box(bbox_object); filler_base_interface->set_bounding_box(bbox_object);
filler_support->set_bounding_box(bbox_object); filler_support->set_bounding_box(bbox_object);
@ -4402,10 +4412,12 @@ void generate_support_toolpaths(
if (idx_layer_intermediate < intermediate_layers.size() && intermediate_layers[idx_layer_intermediate]->print_z < support_layer.print_z + EPSILON) if (idx_layer_intermediate < intermediate_layers.size() && intermediate_layers[idx_layer_intermediate]->print_z < support_layer.print_z + EPSILON)
base_layer.layer = intermediate_layers[idx_layer_intermediate]; base_layer.layer = intermediate_layers[idx_layer_intermediate];
bool raft_layer = support_layer_id == n_raft_layers;
if (config.support_material_interface_layers == 0) { if (config.support_material_interface_layers == 0) {
// If no top interface layers were requested, we treat the contact layer exactly as a generic base layer. // If no top interface layers were requested, we treat the contact layer exactly as a generic base layer.
if (support_params.can_merge_support_regions) { // Don't merge the raft contact layer though.
if (base_layer.could_merge(top_contact_layer)) if (support_params.can_merge_support_regions && ! raft_layer) {
if (base_layer.could_merge(top_contact_layer))
base_layer.merge(std::move(top_contact_layer)); base_layer.merge(std::move(top_contact_layer));
else if (base_layer.empty()) else if (base_layer.empty())
base_layer = std::move(top_contact_layer); base_layer = std::move(top_contact_layer);
@ -4415,7 +4427,7 @@ void generate_support_toolpaths(
// If no loops are allowed, we treat the contact layer exactly as a generic interface layer. // If no loops are allowed, we treat the contact layer exactly as a generic interface layer.
// Merge interface_layer into top_contact_layer, as the top_contact_layer is not synchronized and therefore it will be used // Merge interface_layer into top_contact_layer, as the top_contact_layer is not synchronized and therefore it will be used
// to trim other layers. // to trim other layers.
if (top_contact_layer.could_merge(interface_layer)) if (top_contact_layer.could_merge(interface_layer) && ! raft_layer)
top_contact_layer.merge(std::move(interface_layer)); top_contact_layer.merge(std::move(interface_layer));
} }
if ((config.support_material_interface_layers == 0 || config.support_material_bottom_interface_layers == 0) && support_params.can_merge_support_regions) { if ((config.support_material_interface_layers == 0 || config.support_material_bottom_interface_layers == 0) && support_params.can_merge_support_regions) {
@ -4423,7 +4435,7 @@ void generate_support_toolpaths(
base_layer.merge(std::move(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) else if (base_layer.empty() && ! bottom_contact_layer.empty() && ! bottom_contact_layer.layer->bridging)
base_layer = std::move(bottom_contact_layer); base_layer = std::move(bottom_contact_layer);
} else if (bottom_contact_layer.could_merge(top_contact_layer)) } else if (bottom_contact_layer.could_merge(top_contact_layer) && ! raft_layer)
top_contact_layer.merge(std::move(bottom_contact_layer)); top_contact_layer.merge(std::move(bottom_contact_layer));
else if (bottom_contact_layer.could_merge(interface_layer)) else if (bottom_contact_layer.could_merge(interface_layer))
bottom_contact_layer.merge(std::move(interface_layer)); bottom_contact_layer.merge(std::move(interface_layer));
@ -4441,35 +4453,44 @@ void generate_support_toolpaths(
#endif #endif
// Top and bottom contacts, interface layers. // Top and bottom contacts, interface layers.
for (size_t i = 0; i < 3; ++ i) { enum class InterfaceLayerType { TopContact, BottomContact, RaftContact, Interface, InterfaceAsBase };
SupportGeneratorLayerExtruded &layer_ex = (i == 0) ? top_contact_layer : (i == 1 ? bottom_contact_layer : interface_layer); auto extrude_interface = [&](SupportGeneratorLayerExtruded &layer_ex, InterfaceLayerType interface_layer_type) {
if (layer_ex.empty() || layer_ex.polygons_to_extrude().empty()) if (! layer_ex.empty() && ! layer_ex.polygons_to_extrude().empty()) {
continue; bool interface_as_base = interface_layer_type == InterfaceLayerType::InterfaceAsBase;
bool interface_as_base = config.support_material_interface_layers.value == 0 || bool raft_contact = interface_layer_type == InterfaceLayerType::RaftContact;
(config.support_material_bottom_interface_layers == 0 && &layer_ex == &bottom_contact_layer); //FIXME Bottom interfaces are extruded with the briding flow. Some bridging layers have its height slightly reduced, therefore
//FIXME Bottom interfaces are extruded with the briding flow. Some bridging layers have its height slightly reduced, therefore // the bridging flow does not quite apply. Reduce the flow to area of an ellipse? (A = pi * a * b)
// the bridging flow does not quite apply. Reduce the flow to area of an ellipse? (A = pi * a * b) auto *filler = raft_contact ? filler_raft_contact : filler_interface.get();
auto interface_flow = layer_ex.layer->bridging ? auto interface_flow = layer_ex.layer->bridging ?
Flow::bridging_flow(layer_ex.layer->height, support_params.support_material_bottom_interface_flow.nozzle_diameter()) : Flow::bridging_flow(layer_ex.layer->height, support_params.support_material_bottom_interface_flow.nozzle_diameter()) :
(interface_as_base ? &support_params.support_material_flow : &support_params.support_material_interface_flow)->with_height(float(layer_ex.layer->height)); (raft_contact ? &support_params.raft_interface_flow :
filler_interface->angle = interface_as_base ? interface_as_base ? &support_params.support_material_flow : &support_params.support_material_interface_flow)
// If zero interface layers are configured, use the same angle as for the base layers. ->with_height(float(layer_ex.layer->height));
angles[support_layer_id % angles.size()] : filler->angle = interface_as_base ?
// Use interface angle for the interface layers. // If zero interface layers are configured, use the same angle as for the base layers.
support_params.interface_angle + interface_angle_delta; angles[support_layer_id % angles.size()] :
double density = interface_as_base ? support_params.support_density : support_params.interface_density; // Use interface angle for the interface layers.
filler_interface->spacing = interface_as_base ? support_params.support_material_flow.spacing() : support_params.support_material_interface_flow.spacing(); support_params.interface_angle + interface_angle_delta;
filler_interface->link_max_length = coord_t(scale_(filler_interface->spacing * link_max_length_factor / density)); double density = raft_contact ? support_params.raft_interface_density : interface_as_base ? support_params.support_density : support_params.interface_density;
fill_expolygons_generate_paths( filler->spacing = raft_contact ? support_params.raft_interface_flow.spacing() :
// Destination interface_as_base ? support_params.support_material_flow.spacing() : support_params.support_material_interface_flow.spacing();
layer_ex.extrusions, filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / density));
// Regions to fill fill_expolygons_generate_paths(
union_safety_offset_ex(layer_ex.polygons_to_extrude()), // Destination
// Filler and its parameters layer_ex.extrusions,
filler_interface.get(), float(density), // Regions to fill
// Extrusion parameters union_safety_offset_ex(layer_ex.polygons_to_extrude()),
ExtrusionRole::SupportMaterialInterface, interface_flow); // Filler and its parameters
} filler, float(density),
// Extrusion parameters
ExtrusionRole::SupportMaterialInterface, interface_flow);
}
};
const bool top_interfaces = config.support_material_interface_layers.value != 0;
const bool bottom_interfaces = top_interfaces && config.support_material_bottom_interface_layers != 0;
extrude_interface(top_contact_layer, raft_layer ? InterfaceLayerType::RaftContact : top_interfaces ? InterfaceLayerType::TopContact : InterfaceLayerType::InterfaceAsBase);
extrude_interface(bottom_contact_layer, bottom_interfaces ? InterfaceLayerType::BottomContact : InterfaceLayerType::InterfaceAsBase);
extrude_interface(interface_layer, top_interfaces ? InterfaceLayerType::Interface : InterfaceLayerType::InterfaceAsBase);
// Base interface layers under soluble interfaces // Base interface layers under soluble interfaces
if ( ! base_interface_layer.empty() && ! base_interface_layer.polygons_to_extrude().empty()) { if ( ! base_interface_layer.empty() && ! base_interface_layer.polygons_to_extrude().empty()) {

View File

@ -122,10 +122,17 @@ using SupportGeneratorLayersPtr = std::vector<SupportGeneratorLayer*>;
struct SupportParameters { struct SupportParameters {
SupportParameters(const PrintObject &object); SupportParameters(const PrintObject &object);
// Flow at the 1st print layer.
Flow first_layer_flow; Flow first_layer_flow;
// Flow at the support base (neither top, nor bottom interface).
// Also flow at the raft base with the exception of raft interface and contact layers.
Flow support_material_flow; Flow support_material_flow;
// Flow at the top interface and contact layers.
Flow support_material_interface_flow; Flow support_material_interface_flow;
// Flow at the bottom interfaces and contacts.
Flow support_material_bottom_interface_flow; Flow support_material_bottom_interface_flow;
// Flow at raft inteface & contact layers.
Flow raft_interface_flow;
// Is merging of regions allowed? Could the interface & base support regions be printed with the same extruder? // Is merging of regions allowed? Could the interface & base support regions be printed with the same extruder?
bool can_merge_support_regions; bool can_merge_support_regions;
@ -136,14 +143,23 @@ struct SupportParameters {
float base_angle; float base_angle;
float interface_angle; float interface_angle;
coordf_t interface_spacing;
// Density of the top / bottom interface and contact layers.
coordf_t interface_density; coordf_t interface_density;
coordf_t support_spacing; // Density of the raft interface and contact layers.
coordf_t raft_interface_density;
// Density of the base support layers.
coordf_t support_density; coordf_t support_density;
// Pattern of the sparse infill including sparse raft layers.
InfillPattern base_fill_pattern; InfillPattern base_fill_pattern;
// Pattern of the top / bottom interface and contact layers.
InfillPattern interface_fill_pattern; InfillPattern interface_fill_pattern;
// Pattern of the raft interface and contact layers.
InfillPattern raft_interface_fill_pattern;
// Pattern of the contact layers.
InfillPattern contact_fill_pattern; InfillPattern contact_fill_pattern;
// Shall the sparse (base) layers be printed with a single perimeter line (sheath) for robustness?
bool with_sheath; bool with_sheath;
}; };