2014-01-05 12:16:13 +00:00
# include "Flow.hpp"
2017-05-03 16:28:22 +00:00
# include "Print.hpp"
2014-01-05 12:16:13 +00:00
# include <cmath>
2015-12-11 20:36:51 +00:00
# include <assert.h>
2014-01-05 12:16:13 +00:00
namespace Slic3r {
2014-06-11 23:00:13 +00:00
/* This constructor builds a Flow object from an extrusion width config setting
and other context properties . */
2014-01-05 12:16:13 +00:00
Flow
Flow : : new_from_config_width ( FlowRole role , const ConfigOptionFloatOrPercent & width , float nozzle_diameter , float height , float bridge_flow_ratio ) {
2014-04-05 08:54:24 +00:00
// we need layer height unless it's a bridge
if ( height < = 0 & & bridge_flow_ratio = = 0 ) CONFESS ( " Invalid flow height supplied to new_from_config_width() " ) ;
2014-01-05 12:16:13 +00:00
float w ;
2014-06-11 23:00:13 +00:00
if ( bridge_flow_ratio > 0 ) {
// if bridge flow was requested, calculate bridge width
2014-12-22 15:47:35 +00:00
height = w = Flow : : _bridge_width ( nozzle_diameter , bridge_flow_ratio ) ;
2014-06-11 23:00:13 +00:00
} else if ( ! width . percent & & width . value = = 0 ) {
// if user left option to 0, calculate a sane default width
w = Flow : : _auto_width ( role , nozzle_diameter , height ) ;
2014-01-05 12:16:13 +00:00
} else {
2014-06-11 23:00:13 +00:00
// if user set a manual value, use it
2014-01-05 12:16:13 +00:00
w = width . get_abs_value ( height ) ;
}
2014-06-11 23:00:13 +00:00
return Flow ( w , height , nozzle_diameter , bridge_flow_ratio > 0 ) ;
2014-01-05 12:16:13 +00:00
}
2014-06-11 23:00:13 +00:00
/* This constructor builds a Flow object from a given centerline spacing. */
2014-01-05 12:16:13 +00:00
Flow
Flow : : new_from_spacing ( float spacing , float nozzle_diameter , float height , bool bridge ) {
2014-04-05 08:54:24 +00:00
// we need layer height unless it's a bridge
if ( height < = 0 & & ! bridge ) CONFESS ( " Invalid flow height supplied to new_from_spacing() " ) ;
2014-01-05 12:16:13 +00:00
float w = Flow : : _width_from_spacing ( spacing , nozzle_diameter , height , bridge ) ;
2015-01-17 22:02:48 +00:00
if ( bridge ) height = w ;
2014-06-11 23:00:13 +00:00
return Flow ( w , height , nozzle_diameter , bridge ) ;
}
/* This method returns the centerline spacing between two adjacent extrusions
having the same extrusion width ( and other properties ) . */
float
2016-11-23 14:51:47 +00:00
Flow : : spacing ( ) const
{
# ifdef HAS_PERIMETER_LINE_OVERLAP
if ( this - > bridge )
2014-06-12 07:15:40 +00:00
return this - > width + BRIDGE_EXTRA_SPACING ;
2014-07-26 13:29:24 +00:00
// rectangle with semicircles at the ends
float min_flow_spacing = this - > width - this - > height * ( 1 - PI / 4.0 ) ;
2016-11-23 14:51:47 +00:00
return this - > width - PERIMETER_LINE_OVERLAP_FACTOR * ( this - > width - min_flow_spacing ) ;
# else
return this - > bridge ? ( this - > width + BRIDGE_EXTRA_SPACING ) : ( this - > width - this - > height * ( 1 - PI / 4.0 ) ) ;
# endif
2014-01-05 12:16:13 +00:00
}
2014-06-12 07:15:40 +00:00
/* This method returns the centerline spacing between an extrusion using this
flow and another one using another flow .
this - > spacing ( other ) shall return the same value as other . spacing ( * this ) */
float
Flow : : spacing ( const Flow & other ) const {
assert ( this - > height = = other . height ) ;
assert ( this - > bridge = = other . bridge ) ;
2016-11-23 14:51:47 +00:00
return this - > bridge ?
0.5f * this - > width + 0.5f * other . width + BRIDGE_EXTRA_SPACING :
0.5f * this - > spacing ( ) + 0.5f * other . spacing ( ) ;
2014-06-12 07:15:40 +00:00
}
2014-06-11 23:00:13 +00:00
/* This method returns extrusion volume per head move unit. */
2016-11-23 14:51:47 +00:00
double Flow : : mm3_per_mm ( ) const
{
return this - > bridge ?
( this - > width * this - > width ) * PI / 4.0 :
this - > width * this - > height + ( this - > height * this - > height ) / 4.0 * ( PI - 4.0 ) ;
2014-01-05 12:16:13 +00:00
}
2014-06-11 23:00:13 +00:00
/* This static method returns bridge width for a given nozzle diameter. */
2016-10-16 14:30:56 +00:00
float Flow : : _bridge_width ( float nozzle_diameter , float bridge_flow_ratio ) {
return ( bridge_flow_ratio = = 1. ) ?
// optimization to avoid sqrt()
nozzle_diameter :
sqrt ( bridge_flow_ratio ) * nozzle_diameter ;
2014-06-11 23:00:13 +00:00
}
/* This static method returns a sane extrusion width default. */
2016-11-23 14:51:47 +00:00
float Flow : : _auto_width ( FlowRole role , float nozzle_diameter , float height ) {
2014-01-05 12:16:13 +00:00
// here we calculate a sane default by matching the flow speed (at the nozzle) and the feed rate
2014-07-26 13:29:24 +00:00
// shape: rectangle with semicircles at the ends
float width = ( ( nozzle_diameter * nozzle_diameter ) * PI + ( height * height ) * ( 4.0 - PI ) ) / ( 4.0 * height ) ;
2014-01-05 12:16:13 +00:00
float min = nozzle_diameter * 1.05 ;
float max = - 1 ;
2014-11-07 22:35:33 +00:00
if ( role = = frExternalPerimeter | | role = = frSupportMaterial | | role = = frSupportMaterialInterface ) {
2014-01-05 12:16:13 +00:00
min = max = nozzle_diameter ;
} else if ( role ! = frInfill ) {
// do not limit width for sparse infill so that we use full native flow for it
max = nozzle_diameter * 1.7 ;
}
if ( max ! = - 1 & & width > max ) width = max ;
if ( width < min ) width = min ;
return width ;
}
2014-06-11 23:00:13 +00:00
/* This static method returns the extrusion width value corresponding to the supplied centerline spacing. */
2016-11-23 14:51:47 +00:00
float Flow : : _width_from_spacing ( float spacing , float nozzle_diameter , float height , bool bridge )
{
return bridge ?
( spacing - BRIDGE_EXTRA_SPACING ) :
# ifdef HAS_PERIMETER_LINE_OVERLAP
( spacing + PERIMETER_LINE_OVERLAP_FACTOR * height * ( 1 - PI / 4.0 ) ) ;
# else
( spacing + height * ( 1 - PI / 4.0 ) ) ;
# endif
2014-01-05 12:16:13 +00:00
}
2017-05-03 16:28:22 +00:00
Flow support_material_flow ( const PrintObject * object , float layer_height )
{
return Flow : : new_from_config_width (
frSupportMaterial ,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
( object - > config . support_material_extrusion_width . value > 0 ) ? object - > config . support_material_extrusion_width : object - > config . extrusion_width ,
// if object->config.support_material_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
float ( object - > print ( ) - > config . nozzle_diameter . get_at ( object - > config . support_material_extruder - 1 ) ) ,
( layer_height > 0.f ) ? layer_height : float ( object - > config . layer_height . value ) ,
false ) ;
}
Flow support_material_1st_layer_flow ( const PrintObject * object , float layer_height )
{
return Flow : : new_from_config_width (
frSupportMaterial ,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
( object - > print ( ) - > config . first_layer_extrusion_width . value > 0 ) ? object - > print ( ) - > config . first_layer_extrusion_width : object - > config . support_material_extrusion_width ,
float ( object - > print ( ) - > config . nozzle_diameter . get_at ( object - > config . support_material_extruder - 1 ) ) ,
( layer_height > 0.f ) ? layer_height : object - > config . first_layer_height . get_abs_value ( object - > config . layer_height . value ) ,
false ) ;
}
Flow support_material_interface_flow ( const PrintObject * object , float layer_height )
{
return Flow : : new_from_config_width (
frSupportMaterialInterface ,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
( object - > config . support_material_extrusion_width > 0 ) ? object - > config . support_material_extrusion_width : object - > config . extrusion_width ,
// if object->config.support_material_interface_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
float ( object - > print ( ) - > config . nozzle_diameter . get_at ( object - > config . support_material_interface_extruder - 1 ) ) ,
( layer_height > 0.f ) ? layer_height : float ( object - > config . layer_height . value ) ,
false ) ;
}
2014-01-05 12:16:13 +00:00
}