Ironing support interfaces (#9548)

* Generate support interface iron extrusion

* Always ironing last

* Add options

* Move ironing speed to speed tab

* Don't iron places that are covered by upper support layers

* Disable support interface spacing settings when support ironing is enabled

* Update text
This commit is contained in:
Noisyfox
2025-06-19 15:19:05 +08:00
committed by GitHub
parent 961b73c6be
commit b9cce6c179
10 changed files with 171 additions and 16 deletions

View File

@@ -1605,6 +1605,9 @@ void generate_support_toolpaths(
SupportGeneratorLayerExtruded base_interface_layer;
boost::container::static_vector<LayerCacheItem, 5> nonempty;
float ironing_angle;
Polygons polys_to_iron;
void add_nonempty_and_sort() {
for (SupportGeneratorLayerExtruded *item : { &bottom_contact_layer, &top_contact_layer, &interface_layer, &base_interface_layer, &base_layer })
if (! item->empty())
@@ -1694,6 +1697,12 @@ void generate_support_toolpaths(
base_layer = std::move(top_contact_layer);
}
} else {
if (support_params.ironing && !top_contact_layer.empty()) {
// Orca: save the top surface to be ironed later
layer_cache.ironing_angle = support_interface_angle; // TODO: should we rotate 90 degrees?
layer_cache.polys_to_iron = top_contact_layer.polygons_to_extrude();
}
loop_interface_processor.generate(top_contact_layer, support_params.support_material_interface_flow);
// 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
@@ -1886,7 +1895,7 @@ void generate_support_toolpaths(
// Now modulate the support layer height in parallel.
tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, support_layers.size()),
[&support_layers, &layer_caches]
[&support_layers, &layer_caches, &support_params, &bbox_object]
(const tbb::blocked_range<size_t>& range) {
for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id) {
SupportLayer &support_layer = *support_layers[support_layer_id];
@@ -1897,6 +1906,39 @@ void generate_support_toolpaths(
modulate_extrusion_by_overlapping_layers(layer_cache_item.layer_extruded->extrusions, *layer_cache_item.layer_extruded->layer, layer_cache_item.overlapping);
support_layer.support_fills.append(std::move(layer_cache_item.layer_extruded->extrusions));
}
// Orca: Generate iron toolpath for contact layer
if (!layer_cache.polys_to_iron.empty()) {
auto f = std::unique_ptr<Fill>(Fill::new_from_type(support_params.ironing_pattern));
f->set_bounding_box(bbox_object);
f->layer_id = support_layer.id();
f->z = support_layer.print_z;
f->overlap = 0;
f->angle = layer_cache.ironing_angle;
f->spacing = support_params.ironing_spacing;
f->link_max_length = (coord_t) scale_(3. * f->spacing);
ExPolygons polys_to_iron = union_safety_offset_ex(layer_cache.polys_to_iron);
layer_cache.polys_to_iron.clear();
// Find the layer above that directly overlaps current layer, clip the overlapped part
if (support_layer_id < support_layers.size() - 1) {
const auto& upper_layer = support_layers[support_layer_id + 1];
if (!upper_layer->support_islands.empty() && upper_layer->bottom_z() <= support_layer.print_z + EPSILON) {
polys_to_iron = diff_ex(polys_to_iron, upper_layer->support_islands);
}
}
fill_expolygons_generate_paths(
// Destination
support_layer.support_fills.entities,
// Regions to fill
std::move(polys_to_iron),
// Filler and its parameters
f.get(), 1.f,
// Extrusion parameters
ExtrusionRole::erIroning, support_params.ironing_flow);
}
}
});