mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-15 17:42:14 +00:00
Fix hybrid tree first-layer support base behavior and expose density setting (#13454)
Fix hybrid tree first-layer support base flow and UI consistency Fix incorrect first-layer generation for hybrid tree supports. The support base on the first layer used brim flow instead of support material flow, which could lead to incorrect extrusion behavior and wrong material usage in multi-material prints. Additionally, spacing and density for the regular support part were not consistently derived from the actual first-layer support flow when first-layer and regular line widths differed. Hybrid-specific behavior is clarified: - first-layer expansion applies only to the regular support part - tree-only regions keep their existing behavior The first-layer support pattern is aligned with normal and organic tree supports to ensure consistent and meaningful density behavior. Also make first-layer support expansion and density settings visible whenever supports are enabled, as density was already affecting hybrid supports but was hidden in the UI.
This commit is contained in:
@@ -1593,13 +1593,20 @@ void TreeSupport::generate_toolpaths()
|
||||
}
|
||||
else {
|
||||
// base_areas
|
||||
Flow flow = (layer_id == 0 && m_raft_layers == 0) ? m_object->print()->brim_flow() : support_flow;
|
||||
bool support_base_on_bed = (layer_id == 0 && m_raft_layers == 0);
|
||||
Flow flow = support_base_on_bed ? m_support_params.first_layer_flow : support_flow;
|
||||
bool need_infill = with_infill;
|
||||
if(m_object_config->support_base_pattern==smpDefault)
|
||||
need_infill &= area_group.need_infill;
|
||||
std::shared_ptr<Fill> filler_support = std::shared_ptr<Fill>(Fill::new_from_type(layer_id == 0 ? ipConcentric : m_support_params.base_fill_pattern));
|
||||
// Orca: Use rectilinear for support base on the bed
|
||||
const InfillPattern base_fill_pattern = support_base_on_bed ? ipRectilinear : m_support_params.base_fill_pattern;
|
||||
std::shared_ptr<Fill> filler_support = std::shared_ptr<Fill>(Fill::new_from_type(base_fill_pattern));
|
||||
filler_support->set_bounding_box(bbox_object);
|
||||
filler_support->spacing = support_spacing * support_density; // constant spacing to align support infill lines
|
||||
|
||||
filler_support->spacing =
|
||||
support_base_on_bed ?
|
||||
flow.spacing() : // Orca: On the bed-contacting support base layer, use first-layer flow spacing directly.
|
||||
support_spacing * support_density; // constant spacing to align support infill lines
|
||||
filler_support->angle = Geometry::deg2rad(object_config.support_angle.value);
|
||||
|
||||
Polygons loops = to_polygons(poly);
|
||||
@@ -1639,7 +1646,7 @@ void TreeSupport::generate_toolpaths()
|
||||
// strengthen lightnings while it may make support harder. decide to enable it or not. if yes, proper values for params are remained to be tested
|
||||
auto& lightning_layer = generator->getTreesForLayer(printZ_to_lightninglayer[print_z]);
|
||||
|
||||
Flow flow = (layer_id == 0 && m_raft_layers == 0) ? m_object->print()->brim_flow() :support_flow;
|
||||
Flow flow = (layer_id == 0 && m_raft_layers == 0) ? m_support_params.first_layer_flow : support_flow;
|
||||
ExPolygons areas = offset_ex(ts_layer->base_areas, -flow.scaled_spacing());
|
||||
|
||||
for (auto& area : areas)
|
||||
@@ -2342,6 +2349,31 @@ void TreeSupport::draw_circles()
|
||||
floor_areas = std::move(new_floor_areas);
|
||||
}
|
||||
|
||||
// Orca: Hybrid tree first-layer expansion belongs only to the normal-support
|
||||
// part. area_poly is collected from ePolygon nodes above, which are the normal
|
||||
// support nodes in Hybrid mode. Apply the expansion before area_groups and
|
||||
// lslices are built so toolpaths and brim avoidance use the same footprint.
|
||||
if (layer_nr == 0 && m_raft_layers == 0 && m_support_params.support_style == smsTreeHybrid &&
|
||||
m_object_config->raft_first_layer_expansion.value > 0.f) {
|
||||
ExPolygons expanded_base_areas;
|
||||
const float inflate_factor_1st_layer = float(scale_(m_object_config->raft_first_layer_expansion.value));
|
||||
Polygons trimming = offset(m_object->layers().front()->lslices, float(scale_(m_support_params.gap_xy_first_layer)),
|
||||
SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||
// Orca: Match normal support expansion: grow in steps and re-trim against the object each time.
|
||||
const int nsteps = std::max(5, int(ceil(inflate_factor_1st_layer / m_support_params.first_layer_flow.scaled_width())));
|
||||
const float step = inflate_factor_1st_layer / nsteps;
|
||||
for (const ExPolygon &expoly : ts_layer->base_areas) {
|
||||
if (overlaps({ expoly }, area_poly)) { // normal support in Hybrid mode
|
||||
Polygons expanded = to_polygons(expoly);
|
||||
for (int i = 0; i < nsteps; ++i)
|
||||
expanded = diff(expand(expanded, step), trimming);
|
||||
append(expanded_base_areas, union_ex(expanded));
|
||||
} else
|
||||
expanded_base_areas.emplace_back(expoly);
|
||||
}
|
||||
ts_layer->base_areas = std::move(expanded_base_areas);
|
||||
}
|
||||
|
||||
auto &area_groups = ts_layer->area_groups;
|
||||
|
||||
for (auto& expoly : ts_layer->base_areas) {
|
||||
|
||||
@@ -788,9 +788,12 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||
|
||||
toggle_line("raft_contact_distance", have_raft && !have_support_soluble);
|
||||
|
||||
// Orca: Raft, grid, snug and organic supports use these two parameters to control the size & density of the "brim"/flange
|
||||
for (auto el : { "raft_first_layer_expansion", "raft_first_layer_density"})
|
||||
toggle_field(el, have_support_material && !(support_is_normal_tree && !have_raft));
|
||||
// Orca: First-layer density is available for supports broadly.
|
||||
toggle_field("raft_first_layer_density", have_support_material);
|
||||
// Orca: For regular tree (Slim/Strong) without raft, hide first-layer expansion.
|
||||
// Keep it enabled for non-tree supports, organic tree, hybrid tree, and any raft case.
|
||||
toggle_field("raft_first_layer_expansion",
|
||||
have_support_material && ((!support_is_normal_tree || support_style == smsTreeHybrid) || have_raft));
|
||||
|
||||
bool has_ironing = (config->opt_enum<IroningType>("ironing_type") != IroningType::NoIroning);
|
||||
for (auto el : { "ironing_pattern", "ironing_flow", "ironing_spacing", "ironing_angle", "ironing_inset", "ironing_angle_fixed" })
|
||||
|
||||
Reference in New Issue
Block a user