Replace TreeSupport::SupportParams with SupportParameters

(cherry picked from commit bambulab/BambuStudio@39ae64fc53)

Co-authored-by: Arthur <arthur.tang@bambulab.com>
This commit is contained in:
Noisyfox 2025-01-26 17:08:07 +08:00
parent 824f9efb69
commit 4034ffea18
4 changed files with 45 additions and 73 deletions

View file

@ -140,8 +140,8 @@ std::pair<SupportGeneratorLayersPtr, SupportGeneratorLayersPtr> generate_interfa
if (! intermediate_layers.empty() && support_params.has_interfaces()) { if (! intermediate_layers.empty() && support_params.has_interfaces()) {
// For all intermediate layers, collect top contact surfaces, which are not further than support_material_interface_layers. // 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"; BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_interface_layers() in parallel - start";
const bool snug_supports = config.support_style.value == smsSnug; const bool snug_supports = support_params.support_style == smsSnug;
const bool smooth_supports = config.support_style.value != smsGrid; const bool smooth_supports = support_params.support_style != smsGrid;
SupportGeneratorLayersPtr &interface_layers = base_and_interface_layers.first; SupportGeneratorLayersPtr &interface_layers = base_and_interface_layers.first;
SupportGeneratorLayersPtr &base_interface_layers = base_and_interface_layers.second; SupportGeneratorLayersPtr &base_interface_layers = base_and_interface_layers.second;
interface_layers.assign(intermediate_layers.size(), nullptr); interface_layers.assign(intermediate_layers.size(), nullptr);
@ -1646,7 +1646,7 @@ void generate_support_toolpaths(
{ {
SupportLayer &support_layer = *support_layers[support_layer_id]; SupportLayer &support_layer = *support_layers[support_layer_id];
LayerCache &layer_cache = layer_caches[support_layer_id]; LayerCache &layer_cache = layer_caches[support_layer_id];
const float support_interface_angle = config.support_style.value == smsGrid ? const float support_interface_angle = support_params.support_style == smsGrid ?
support_params.interface_angle : support_params.raft_interface_angle(support_layer.interface_id()); support_params.interface_angle : support_params.raft_interface_angle(support_layer.interface_id());
// Find polygons with the same print_z. // Find polygons with the same print_z.
@ -1808,9 +1808,7 @@ void generate_support_toolpaths(
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));
sheath = true; sheath = true;
no_sort = true; no_sort = true;
} else if (config.support_style == SupportMaterialStyle::smsOrganic || } else if (support_params.support_style == SupportMaterialStyle::smsOrganic) {
// Orca: use organic as default
config.support_style == smsDefault) {
tree_supports_generate_paths(base_layer.extrusions, base_layer.polygons_to_extrude(), flow, support_params); tree_supports_generate_paths(base_layer.extrusions, base_layer.polygons_to_extrude(), flow, support_params);
done = true; done = true;
} }

View file

@ -104,7 +104,12 @@ struct SupportParameters {
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->raft_interface_fill_pattern = this->raft_interface_density > 0.95 ? ipRectilinear : ipSupportBase;
this->contact_fill_pattern = if (object_config.support_interface_pattern == smipGrid)
this->contact_fill_pattern = ipGrid;
else if (object_config.support_interface_pattern == smipRectilinearInterlaced)
this->contact_fill_pattern = ipRectilinear;
else
this->contact_fill_pattern =
(object_config.support_interface_pattern == smipAuto && slicing_params.soluble_interface) || (object_config.support_interface_pattern == smipAuto && slicing_params.soluble_interface) ||
object_config.support_interface_pattern == smipConcentric ? object_config.support_interface_pattern == smipConcentric ?
ipConcentric : ipConcentric :
@ -143,10 +148,24 @@ struct SupportParameters {
assert(slicing_params.raft_layers() == 0); assert(slicing_params.raft_layers() == 0);
} }
this->tree_branch_diameter_double_wall_area_scaled = 0.25 * sqr(scaled<double>(object_config.tree_support_branch_diameter_double_wall.value)) * M_PI; const auto nozzle_diameter = print_config.nozzle_diameter.get_at(object_config.support_interface_filament - 1);
} const coordf_t extrusion_width = object_config.line_width.get_abs_value(nozzle_diameter);
support_extrusion_width = object_config.support_line_width.get_abs_value(nozzle_diameter);
support_extrusion_width = support_extrusion_width > 0 ? support_extrusion_width : extrusion_width;
// Both top / bottom contacts and interfaces are soluble. tree_branch_diameter_double_wall_area_scaled = 0.25 * sqr(scaled<double>(object_config.tree_support_branch_diameter_double_wall.value)) * M_PI;
support_style = object_config.support_style;
if (support_style == smsDefault) {
if (is_tree(object_config.support_type)) {
// Orca: use organic as default
support_style = smsOrganic;
} else {
support_style = smsGrid;
}
}
}
// Both top / bottom contacts and interfaces are soluble.
bool soluble_interface; bool soluble_interface;
// Support contact & interface are soluble, but support base is non-soluble. // Support contact & interface are soluble, but support base is non-soluble.
bool soluble_interface_non_soluble_base; bool soluble_interface_non_soluble_base;
@ -181,6 +200,7 @@ struct SupportParameters {
Flow support_material_bottom_interface_flow; Flow support_material_bottom_interface_flow;
// Flow at raft inteface & contact layers. // Flow at raft inteface & contact layers.
Flow raft_interface_flow; Flow raft_interface_flow;
coordf_t support_extrusion_width;
// 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;
@ -198,6 +218,7 @@ struct SupportParameters {
coordf_t raft_interface_density; coordf_t raft_interface_density;
// Density of the base support layers. // Density of the base support layers.
coordf_t support_density; coordf_t support_density;
SupportMaterialStyle support_style = smsDefault;
// Pattern of the sparse infill including sparse raft layers. // Pattern of the sparse infill including sparse raft layers.
InfillPattern base_fill_pattern; InfillPattern base_fill_pattern;
@ -219,6 +240,8 @@ struct SupportParameters {
// Produce a raft interface angle for a given SupportLayer::interface_id() // Produce a raft interface angle for a given SupportLayer::interface_id()
float raft_interface_angle(size_t interface_id) const float raft_interface_angle(size_t interface_id) const
{ return this->raft_angle_interface + ((interface_id & 1) ? float(- M_PI / 4.) : float(+ M_PI / 4.)); } { return this->raft_angle_interface + ((interface_id & 1) ? float(- M_PI / 4.) : float(+ M_PI / 4.)); }
const double thresh_big_overhang = Slic3r::sqr(scale_(10));
}; };
} // namespace Slic3r } // namespace Slic3r

View file

@ -667,41 +667,21 @@ static Point bounding_box_middle(const BoundingBox &bbox)
} }
TreeSupport::TreeSupport(PrintObject& object, const SlicingParameters &slicing_params) TreeSupport::TreeSupport(PrintObject& object, const SlicingParameters &slicing_params)
: m_object(&object), m_slicing_params(slicing_params), m_object_config(&object.config()) : m_object(&object), m_slicing_params(slicing_params), m_support_params(object), m_object_config(&object.config())
{ {
m_print_config = &m_object->print()->config(); m_print_config = &m_object->print()->config();
m_raft_layers = slicing_params.base_raft_layers + slicing_params.interface_raft_layers; m_raft_layers = slicing_params.base_raft_layers + slicing_params.interface_raft_layers;
support_type = m_object_config->support_type; support_type = m_object_config->support_type;
support_style = m_object_config->support_style;
if (support_style == smsDefault)
// Orca: use organic as default
support_style = smsOrganic;
SupportMaterialPattern support_pattern = m_object_config->support_base_pattern; SupportMaterialPattern support_pattern = m_object_config->support_base_pattern;
if (support_style == smsTreeHybrid && support_pattern == smpDefault) if (m_support_params.support_style == smsTreeHybrid && support_pattern == smpDefault)
support_pattern = smpRectilinear; support_pattern = smpRectilinear;
m_support_params.base_fill_pattern =
support_pattern == smpLightning ? ipLightning :
support_pattern == smpHoneycomb ? ipHoneycomb :
m_support_params.support_density > 0.95 || m_support_params.with_sheath ? ipRectilinear : ipSupportBase;
m_support_params.interface_fill_pattern = (m_support_params.interface_density > 0.95 ? ipRectilinear : ipSupportBase); if(support_pattern == smpLightning)
if (m_object_config->support_interface_pattern == smipGrid) m_support_params.base_fill_pattern = ipLightning;
m_support_params.contact_fill_pattern = ipGrid;
else if (m_object_config->support_interface_pattern == smipRectilinearInterlaced)
m_support_params.contact_fill_pattern = ipRectilinear;
else
m_support_params.contact_fill_pattern = (m_object_config->support_interface_pattern == smipAuto && m_slicing_params.soluble_interface) ||
m_object_config->support_interface_pattern == smipConcentric ?
ipConcentric :
(m_support_params.interface_density > 0.95 ? ipRectilinear : ipSupportBase);
const auto nozzle_diameter = object.print()->config().nozzle_diameter.get_at(object.config().support_interface_filament-1); is_slim = is_tree_slim(support_type, m_support_params.support_style);
const coordf_t extrusion_width = m_object_config->line_width.get_abs_value(nozzle_diameter); is_strong = is_tree(support_type) && m_support_params.support_style == smsTreeStrong;
const coordf_t support_extrusion_width = m_object_config->support_line_width.get_abs_value(nozzle_diameter);
m_support_params.support_extrusion_width = support_extrusion_width > 0 ? support_extrusion_width : extrusion_width;
is_slim = is_tree_slim(support_type, support_style);
is_strong = is_tree(support_type) && support_style == smsTreeStrong;
MAX_BRANCH_RADIUS = 10.0; MAX_BRANCH_RADIUS = 10.0;
tree_support_branch_diameter_angle = 5.0;//is_slim ? 10.0 : 5.0; tree_support_branch_diameter_angle = 5.0;//is_slim ? 10.0 : 5.0;
// by default tree support needs no infill, unless it's tree hybrid which contains normal nodes. // by default tree support needs no infill, unless it's tree hybrid which contains normal nodes.
@ -1132,7 +1112,7 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
if (max_bridge_length > 0 && ts_layer->overhang_areas.size() > 0 && lower_layer) { if (max_bridge_length > 0 && ts_layer->overhang_areas.size() > 0 && lower_layer) {
// do not break bridge for normal part in TreeHybrid // do not break bridge for normal part in TreeHybrid
bool break_bridge = !(support_style == smsTreeHybrid && area(ts_layer->overhang_areas) > m_support_params.thresh_big_overhang); bool break_bridge = !(m_support_params.support_style == smsTreeHybrid && area(ts_layer->overhang_areas) > m_support_params.thresh_big_overhang);
m_object->remove_bridges_from_contacts(lower_layer, layer, extrusion_width_scaled, &ts_layer->overhang_areas, max_bridge_length, break_bridge); m_object->remove_bridges_from_contacts(lower_layer, layer, extrusion_width_scaled, &ts_layer->overhang_areas, max_bridge_length, break_bridge);
} }
@ -1587,7 +1567,7 @@ void TreeSupport::generate_toolpaths()
bool need_infill = with_infill; bool need_infill = with_infill;
if(m_object_config->support_base_pattern==smpDefault) if(m_object_config->support_base_pattern==smpDefault)
need_infill &= area_group.need_infill; need_infill &= area_group.need_infill;
if (layer_id>0 && area_group.dist_to_top < 10 && !need_infill && support_style!=smsTreeHybrid) { if (layer_id>0 && area_group.dist_to_top < 10 && !need_infill && m_support_params.support_style!=smsTreeHybrid) {
if (area_group.dist_to_top < 5) // 1 wall at the top <5mm if (area_group.dist_to_top < 5) // 1 wall at the top <5mm
make_perimeter_and_inner_brim(ts_layer->support_fills.entities, poly, 1, flow, erSupportMaterial); make_perimeter_and_inner_brim(ts_layer->support_fills.entities, poly, 1, flow, erSupportMaterial);
else // at least 2 walls for range [5,10) else // at least 2 walls for range [5,10)
@ -1880,7 +1860,7 @@ Polygons TreeSupport::contact_nodes_to_polygon(const std::vector<Node*>& contact
void TreeSupport::generate() void TreeSupport::generate()
{ {
if (support_style == smsOrganic) { if (m_support_params.support_style == smsOrganic) {
generate_tree_support_3D(*m_object, this, this->throw_on_cancel); generate_tree_support_3D(*m_object, this, this->throw_on_cancel);
return; return;
} }
@ -3438,7 +3418,7 @@ void TreeSupport::generate_contact_points(std::vector<std::vector<TreeSupport::N
for (const ExPolygon &overhang_part : overhang) for (const ExPolygon &overhang_part : overhang)
{ {
BoundingBox overhang_bounds = get_extents(overhang_part); BoundingBox overhang_bounds = get_extents(overhang_part);
if (support_style==smsTreeHybrid && overhang_part.area() > m_support_params.thresh_big_overhang) { if (m_support_params.support_style==smsTreeHybrid && overhang_part.area() > m_support_params.thresh_big_overhang) {
Point candidate = overhang_bounds.center(); Point candidate = overhang_bounds.center();
if (!overhang_part.contains(candidate)) if (!overhang_part.contains(candidate))
move_inside_expoly(overhang_part, candidate); move_inside_expoly(overhang_part, candidate);

View file

@ -11,6 +11,7 @@
#include "Flow.hpp" #include "Flow.hpp"
#include "PrintConfig.hpp" #include "PrintConfig.hpp"
#include "Fill/Lightning/Generator.hpp" #include "Fill/Lightning/Generator.hpp"
#include "TreeSupport3D.hpp"
#ifndef SQ #ifndef SQ
#define SQ(x) ((x)*(x)) #define SQ(x) ((x)*(x))
@ -361,35 +362,6 @@ public:
} }
}; };
struct SupportParams
{
Flow first_layer_flow;
Flow support_material_flow;
Flow support_material_interface_flow;
Flow support_material_bottom_interface_flow;
coordf_t support_extrusion_width;
// Is merging of regions allowed? Could the interface & base support regions be printed with the same extruder?
bool can_merge_support_regions;
coordf_t support_layer_height_min;
// coordf_t support_layer_height_max;
coordf_t gap_xy;
float base_angle;
float interface_angle;
coordf_t interface_spacing;
coordf_t interface_density;
coordf_t support_spacing;
coordf_t support_density;
InfillPattern base_fill_pattern;
InfillPattern interface_fill_pattern;
InfillPattern contact_fill_pattern;
bool with_sheath;
const double thresh_big_overhang = SQ(scale_(10));
};
int avg_node_per_layer = 0; int avg_node_per_layer = 0;
float nodes_angle = 0; float nodes_angle = 0;
bool has_overhangs = false; bool has_overhangs = false;
@ -397,7 +369,6 @@ public:
bool has_cantilever = false; bool has_cantilever = false;
double max_cantilever_dist = 0; double max_cantilever_dist = 0;
SupportType support_type; SupportType support_type;
SupportMaterialStyle support_style;
std::unique_ptr<FillLightning::Generator> generator; std::unique_ptr<FillLightning::Generator> generator;
std::unordered_map<double, size_t> printZ_to_lightninglayer; std::unordered_map<double, size_t> printZ_to_lightninglayer;
@ -422,7 +393,7 @@ private:
const PrintObjectConfig *m_object_config; const PrintObjectConfig *m_object_config;
SlicingParameters m_slicing_params; SlicingParameters m_slicing_params;
// Various precomputed support parameters to be shared with external functions. // Various precomputed support parameters to be shared with external functions.
SupportParams m_support_params; SupportParameters m_support_params;
size_t m_raft_layers = 0; size_t m_raft_layers = 0;
size_t m_highest_overhang_layer = 0; size_t m_highest_overhang_layer = 0;
std::vector<std::vector<MinimumSpanningTree>> m_spanning_trees; std::vector<std::vector<MinimumSpanningTree>> m_spanning_trees;