2023-10-26 11:31:44 +00:00
# pragma once
2024-10-28 15:24:45 +00:00
# include <boost/log/trivial.hpp>
2023-10-26 11:31:44 +00:00
# include "../libslic3r.h"
# include "../Flow.hpp"
# include "../PrintConfig.hpp"
# include "../Slicing.hpp"
# include "../Fill/FillBase.hpp"
# include "../Print.hpp"
# include "../Layer.hpp"
# include "SupportLayer.hpp"
namespace Slic3r {
struct SupportParameters {
2024-08-30 07:13:29 +00:00
SupportParameters ( ) = delete ;
2023-10-26 11:31:44 +00:00
SupportParameters ( const PrintObject & object )
{
const PrintConfig & print_config = object . print ( ) - > config ( ) ;
const PrintObjectConfig & object_config = object . config ( ) ;
const SlicingParameters & slicing_params = object . slicing_parameters ( ) ;
this - > soluble_interface = slicing_params . soluble_interface ;
this - > soluble_interface_non_soluble_base =
// Zero z-gap between the overhangs and the support interface.
slicing_params . soluble_interface & &
// Interface extruder soluble.
object_config . support_interface_filament . value > 0 & & print_config . filament_soluble . get_at ( object_config . support_interface_filament . value - 1 ) & &
// Base extruder: Either "print with active extruder" not soluble.
( object_config . support_filament . value = = 0 | | ! print_config . filament_soluble . get_at ( object_config . support_filament . value - 1 ) ) ;
{
this - > num_top_interface_layers = std : : max ( 0 , object_config . support_interface_top_layers . value ) ;
2024-12-31 06:05:55 +00:00
this - > num_bottom_interface_layers = object_config . support_interface_bottom_layers < 0 ?
2023-10-26 11:31:44 +00:00
num_top_interface_layers : object_config . support_interface_bottom_layers ;
this - > has_top_contacts = num_top_interface_layers > 0 ;
this - > has_bottom_contacts = num_bottom_interface_layers > 0 ;
if ( this - > soluble_interface_non_soluble_base ) {
// Try to support soluble dense interfaces with non-soluble dense interfaces.
this - > num_top_base_interface_layers = size_t ( std : : min ( int ( num_top_interface_layers ) / 2 , 2 ) ) ;
this - > num_bottom_base_interface_layers = size_t ( std : : min ( int ( num_bottom_interface_layers ) / 2 , 2 ) ) ;
} else {
2024-11-06 06:10:08 +00:00
// BBS: if support interface and support base do not use the same filament, add a base layer to improve their adhesion
// Note: support materials (such as Supp.W) can't be used as support base now, so support interface and base are still using different filaments even if
// support_filament==0
bool differnt_support_interface_filament = object_config . support_interface_filament ! = 0 & &
object_config . support_interface_filament ! = object_config . support_filament ;
this - > num_top_base_interface_layers = differnt_support_interface_filament ? 1 : 0 ;
this - > num_bottom_base_interface_layers = differnt_support_interface_filament ? 1 : 0 ;
2023-10-26 11:31:44 +00:00
}
}
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_interface_flow = Slic3r : : support_material_interface_flow ( & object , float ( slicing_params . layer_height ) ) ;
2024-05-28 12:11:45 +00:00
this - > raft_interface_flow = support_material_interface_flow ;
2023-10-26 11:31:44 +00:00
// 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 ) ;
for ( auto lh : print_config . min_layer_height . values )
this - > support_layer_height_min = std : : min ( this - > support_layer_height_min , std : : max ( 0.01 , lh ) ) ;
for ( auto layer : object . layers ( ) )
this - > support_layer_height_min = std : : min ( this - > support_layer_height_min , std : : max ( 0.01 , layer - > height ) ) ;
if ( object_config . support_interface_top_layers . value = = 0 ) {
// No interface layers allowed, print everything with the base support pattern.
this - > support_material_interface_flow = this - > support_material_flow ;
}
// Evaluate the XY gap between the object outer perimeters and the support structures.
// Evaluate the XY gap between the object outer perimeters and the support structures.
coordf_t external_perimeter_width = 0. ;
coordf_t bridge_flow_ratio = 0 ;
for ( size_t region_id = 0 ; region_id < object . num_printing_regions ( ) ; + + region_id ) {
const PrintRegion & region = object . printing_region ( region_id ) ;
external_perimeter_width = std : : max ( external_perimeter_width , coordf_t ( region . flow ( object , frExternalPerimeter , slicing_params . layer_height ) . width ( ) ) ) ;
bridge_flow_ratio + = region . config ( ) . bridge_flow ;
}
this - > gap_xy = object_config . support_object_xy_distance . value ;
2024-03-06 00:44:32 +00:00
this - > gap_xy_first_layer = object_config . support_object_first_layer_gap . value ;
2023-10-26 11:31:44 +00:00
bridge_flow_ratio / = object . num_printing_regions ( ) ;
this - > support_material_bottom_interface_flow = slicing_params . soluble_interface | | ! object_config . thick_bridges ?
this - > support_material_interface_flow . with_flow_ratio ( bridge_flow_ratio ) :
Flow : : bridging_flow ( bridge_flow_ratio * this - > support_material_interface_flow . nozzle_diameter ( ) , this - > support_material_interface_flow . nozzle_diameter ( ) ) ;
this - > can_merge_support_regions = object_config . support_filament . value = = object_config . support_interface_filament . value ;
if ( ! this - > can_merge_support_regions & & ( object_config . support_filament . value = = 0 | | object_config . support_interface_filament . value = = 0 ) ) {
// One of the support extruders is of "don't care" type.
auto object_extruders = object . object_extruders ( ) ;
if ( object_extruders . size ( ) = = 1 & &
// object_extruders are 0-based but object_config.support_filament's are 1-based
object_extruders [ 0 ] + 1 = = std : : max < unsigned int > ( object_config . support_filament . value , object_config . support_interface_filament . value ) )
// Object is printed with the same extruder as the support.
this - > can_merge_support_regions = true ;
}
2023-11-24 12:29:56 +00:00
this - > base_angle = Geometry : : deg2rad ( float ( object_config . support_angle . value ) ) ;
this - > interface_angle = Geometry : : deg2rad ( float ( object_config . support_angle . value + 90. ) ) ;
2023-10-26 11:31:44 +00:00
this - > interface_spacing = object_config . support_interface_spacing . value + this - > support_material_interface_flow . spacing ( ) ;
this - > interface_density = std : : min ( 1. , this - > support_material_interface_flow . spacing ( ) / this - > interface_spacing ) ;
2024-05-28 12:11:45 +00:00
double raft_interface_spacing = object_config . support_interface_spacing . value + this - > raft_interface_flow . spacing ( ) ;
this - > raft_interface_density = std : : min ( 1. , this - > raft_interface_flow . spacing ( ) / raft_interface_spacing ) ;
2023-10-26 11:31:44 +00:00
this - > support_spacing = object_config . support_base_pattern_spacing . value + this - > support_material_flow . spacing ( ) ;
this - > support_density = std : : min ( 1. , this - > support_material_flow . spacing ( ) / this - > support_spacing ) ;
if ( object_config . support_interface_top_layers . value = = 0 ) {
// No interface layers allowed, print everything with the base support pattern.
this - > interface_spacing = this - > support_spacing ;
this - > interface_density = this - > support_density ;
}
SupportMaterialPattern support_pattern = object_config . support_base_pattern ;
2024-05-28 12:11:45 +00:00
this - > with_sheath = object_config . tree_support_wall_count > 0 ;
2023-10-26 11:31:44 +00:00
this - > base_fill_pattern =
support_pattern = = smpHoneycomb ? ipHoneycomb :
this - > support_density > 0.95 | | this - > with_sheath ? ipRectilinear : ipSupportBase ;
this - > interface_fill_pattern = ( this - > interface_density > 0.95 ? ipRectilinear : ipSupportBase ) ;
2024-05-28 12:11:45 +00:00
this - > raft_interface_fill_pattern = this - > raft_interface_density > 0.95 ? ipRectilinear : ipSupportBase ;
2023-10-26 11:31:44 +00:00
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 = = smipConcentric ?
ipConcentric :
( this - > interface_density > 0.95 ? ipRectilinear : ipSupportBase ) ;
2024-12-31 06:05:55 +00:00
2024-05-28 12:11:45 +00:00
this - > raft_angle_1st_layer = 0.f ;
this - > raft_angle_base = 0.f ;
this - > raft_angle_interface = 0.f ;
if ( slicing_params . base_raft_layers > 1 ) {
assert ( slicing_params . raft_layers ( ) > = 4 ) ;
// There are all raft layer types (1st layer, base, interface & contact layers) available.
this - > raft_angle_1st_layer = this - > interface_angle ;
this - > raft_angle_base = this - > base_angle ;
this - > raft_angle_interface = this - > interface_angle ;
if ( ( slicing_params . interface_raft_layers & 1 ) = = 0 )
// Allign the 1st raft interface layer so that the object 1st layer is hatched perpendicularly to the raft contact interface.
this - > raft_angle_interface + = float ( 0.5 * M_PI ) ;
} else if ( slicing_params . base_raft_layers = = 1 | | slicing_params . interface_raft_layers > 1 ) {
assert ( slicing_params . raft_layers ( ) = = 2 | | slicing_params . raft_layers ( ) = = 3 ) ;
// 1st layer, interface & contact layers available.
this - > raft_angle_1st_layer = this - > base_angle ;
this - > raft_angle_interface = this - > interface_angle + 0.5 * M_PI ;
} else if ( slicing_params . interface_raft_layers = = 1 ) {
// Only the contact raft layer is non-empty, which will be printed as the 1st layer.
assert ( slicing_params . base_raft_layers = = 0 ) ;
assert ( slicing_params . interface_raft_layers = = 1 ) ;
assert ( slicing_params . raft_layers ( ) = = 1 ) ;
this - > raft_angle_1st_layer = float ( 0.5 * M_PI ) ;
this - > raft_angle_interface = this - > raft_angle_1st_layer ;
} else {
// No raft.
assert ( slicing_params . base_raft_layers = = 0 ) ;
assert ( slicing_params . interface_raft_layers = = 0 ) ;
assert ( slicing_params . raft_layers ( ) = = 0 ) ;
}
2024-08-30 07:13:29 +00:00
support_extrusion_width = object_config . support_line_width . value > 0 ? object_config . support_line_width : object_config . line_width ;
// Check if set to zero, use default if so.
if ( support_extrusion_width < = 0.0 ) {
const auto nozzle_diameter = print_config . nozzle_diameter . get_at ( object_config . support_interface_filament - 1 ) ;
support_extrusion_width = Flow : : auto_extrusion_width ( FlowRole : : frSupportMaterial , ( float ) nozzle_diameter ) ;
}
2024-12-31 06:05:55 +00:00
double tree_support_branch_diameter_double_wall = 3.0 ;
// get support filament strength and decide the thresh of double wall area
float support_filament_strength = print_config . impact_strength_z . get_at ( object_config . support_filament - 1 ) ;
if ( object_config . support_filament = = 0 ) {
// find the weakest filament
support_filament_strength = std : : numeric_limits < float > : : max ( ) ;
for ( auto extruder : object . object_extruders ( ) ) {
float strength = print_config . impact_strength_z . get_at ( extruder ) ;
if ( strength < support_filament_strength ) support_filament_strength = strength ;
}
}
2024-08-30 07:13:29 +00:00
2024-12-31 06:05:55 +00:00
if ( object_config . tree_support_wall_count . value = = 0 ) {
tree_support_branch_diameter_double_wall = support_filament_strength ;
this - > tree_branch_diameter_double_wall_area_scaled = 0.25 * sqr ( scaled < double > ( tree_support_branch_diameter_double_wall ) ) * M_PI ;
} else {
// force double walls everywhere if wall count is larger than 1
this - > tree_branch_diameter_double_wall_area_scaled = object_config . tree_support_wall_count . value > 1 ? 0.1 : std : : numeric_limits < double > : : max ( ) ;
}
independent_layer_height = print_config . independent_support_layer_height ;
2024-10-15 06:48:31 +00:00
support_style = object_config . support_style ;
2024-11-18 02:29:22 +00:00
if ( support_style ! = smsDefault ) {
if ( ( support_style = = smsSnug | | support_style = = smsGrid ) & & is_tree ( object_config . support_type ) ) support_style = smsDefault ;
if ( ( support_style = = smsTreeSlim | | support_style = = smsTreeStrong | | support_style = = smsTreeHybrid | | support_style = = smsTreeOrganic ) & &
! is_tree ( object_config . support_type ) )
support_style = smsDefault ;
}
2024-10-15 06:48:31 +00:00
if ( support_style = = smsDefault ) {
2024-10-24 12:10:32 +00:00
if ( is_tree ( object_config . support_type ) ) {
// organic support doesn't work with variable layer heights (including adaptive layer height and height range modifier, see #4313)
2025-02-12 08:21:23 +00:00
if ( ! object . has_variable_layer_heights & & ! slicing_params . soluble_interface ) {
2024-10-24 12:10:32 +00:00
BOOST_LOG_TRIVIAL ( warning ) < < " tree support default to organic support " ;
support_style = smsTreeOrganic ;
} else {
BOOST_LOG_TRIVIAL ( warning ) < < " tree support default to hybrid tree due to adaptive layer height " ;
support_style = smsTreeHybrid ;
}
2024-10-15 06:48:31 +00:00
} else {
2024-10-24 12:10:32 +00:00
support_style = smsGrid ;
2024-10-15 06:48:31 +00:00
}
}
2023-10-26 11:31:44 +00:00
}
// Both top / bottom contacts and interfaces are soluble.
bool soluble_interface ;
// Support contact & interface are soluble, but support base is non-soluble.
bool soluble_interface_non_soluble_base ;
// Is there at least a top contact layer extruded above support base?
bool has_top_contacts ;
// Is there at least a bottom contact layer extruded below support base?
bool has_bottom_contacts ;
// Number of top interface layers without counting the contact layer.
size_t num_top_interface_layers ;
// Number of bottom interface layers without counting the contact layer.
size_t num_bottom_interface_layers ;
// Number of top base interface layers. Zero if not soluble_interface_non_soluble_base.
size_t num_top_base_interface_layers ;
// Number of bottom base interface layers. Zero if not soluble_interface_non_soluble_base.
size_t num_bottom_base_interface_layers ;
bool has_contacts ( ) const { return this - > has_top_contacts | | this - > has_bottom_contacts ; }
bool has_interfaces ( ) const { return this - > num_top_interface_layers + this - > num_bottom_interface_layers > 0 ; }
bool has_base_interfaces ( ) const { return this - > num_top_base_interface_layers + this - > num_bottom_base_interface_layers > 0 ; }
size_t num_top_interface_layers_only ( ) const { return this - > num_top_interface_layers - this - > num_top_base_interface_layers ; }
size_t num_bottom_interface_layers_only ( ) const { return this - > num_bottom_interface_layers - this - > num_bottom_base_interface_layers ; }
Flow first_layer_flow ;
Flow support_material_flow ;
Flow support_material_interface_flow ;
Flow support_material_bottom_interface_flow ;
2024-05-28 12:11:45 +00:00
// Flow at raft inteface & contact layers.
Flow raft_interface_flow ;
2024-01-06 13:27:46 +00:00
coordf_t support_extrusion_width ;
2023-10-26 11:31:44 +00:00
// 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 ;
2024-03-06 00:44:32 +00:00
coordf_t gap_xy_first_layer ;
2023-10-26 11:31:44 +00:00
float base_angle ;
float interface_angle ;
coordf_t interface_spacing ;
2024-01-06 13:27:46 +00:00
coordf_t support_expansion = 0 ;
2023-10-26 11:31:44 +00:00
coordf_t interface_density ;
2024-05-28 12:11:45 +00:00
// Density of the raft interface and contact layers.
coordf_t raft_interface_density ;
2023-10-26 11:31:44 +00:00
coordf_t support_spacing ;
coordf_t support_density ;
2024-10-15 06:48:31 +00:00
SupportMaterialStyle support_style = smsDefault ;
2023-10-26 11:31:44 +00:00
InfillPattern base_fill_pattern ;
InfillPattern interface_fill_pattern ;
2024-05-28 12:11:45 +00:00
// Pattern of the raft interface and contact layers.
InfillPattern raft_interface_fill_pattern ;
2023-10-26 11:31:44 +00:00
InfillPattern contact_fill_pattern ;
bool with_sheath ;
2024-05-28 12:11:45 +00:00
// Branches of organic supports with area larger than this threshold will be extruded with double lines.
2024-08-30 07:13:29 +00:00
double tree_branch_diameter_double_wall_area_scaled = 0.25 * sqr ( scaled < double > ( 5.0 ) ) * M_PI ; ;
2024-05-28 12:11:45 +00:00
float raft_angle_1st_layer ;
float raft_angle_base ;
float raft_angle_interface ;
// Produce a raft interface angle for a given SupportLayer::interface_id()
2024-12-31 06:05:55 +00:00
float raft_interface_angle ( size_t interface_id ) const
2024-05-28 12:11:45 +00:00
{ return this - > raft_angle_interface + ( ( interface_id & 1 ) ? float ( - M_PI / 4. ) : float ( + M_PI / 4. ) ) ; }
2024-12-31 06:05:55 +00:00
2024-01-06 13:27:46 +00:00
bool independent_layer_height = false ;
2024-12-31 06:05:55 +00:00
const double thresh_big_overhang = /*Slic3r::sqr(scale_(10))*/ scale_ ( 10 ) ;
2023-10-26 11:31:44 +00:00
} ;
} // namespace Slic3r