2017-05-16 11:45:28 +00:00
// Ordering of the tools to minimize tool switches.
# ifndef slic3r_ToolOrdering_hpp_
# define slic3r_ToolOrdering_hpp_
2018-11-26 13:54:23 +00:00
# include "../libslic3r.h"
2017-05-16 11:45:28 +00:00
2020-01-07 13:35:43 +00:00
# include <utility>
2020-01-08 13:58:12 +00:00
# include <boost/container/small_vector.hpp>
2017-05-16 11:45:28 +00:00
namespace Slic3r {
2017-05-25 20:27:53 +00:00
class Print ;
class PrintObject ;
2018-06-26 12:12:25 +00:00
class LayerTools ;
2017-05-25 20:27:53 +00:00
2018-06-20 10:52:00 +00:00
// Object of this class holds information about whether an extrusion is printed immediately
// after a toolchange (as part of infill/perimeter wiping) or not. One extrusion can be a part
// of several copies - this has to be taken into account.
class WipingExtrusions
{
2018-06-26 12:12:25 +00:00
public :
2018-06-20 10:52:00 +00:00
bool is_anything_overridden ( ) const { // if there are no overrides, all the agenda can be skipped - this function can tell us if that's the case
return something_overridden ;
}
2020-01-08 13:58:12 +00:00
// When allocating extruder overrides of an object's ExtrusionEntity, overrides for maximum 3 copies are allocated in place.
typedef boost : : container : : small_vector < int32_t , 3 > ExtruderPerCopy ;
class ExtruderOverrides
{
public :
ExtruderOverrides ( const ExtruderPerCopy * overrides , const int correct_extruder_id ) : m_overrides ( overrides ) { }
private :
const ExtruderPerCopy * m_overrides ;
} ;
2018-06-26 12:12:25 +00:00
// This is called from GCode::process_layer - see implementation for further comments:
2020-01-08 13:58:12 +00:00
const ExtruderPerCopy * get_extruder_overrides ( const ExtrusionEntity * entity , int correct_extruder_id , size_t num_of_copies ) ;
2018-06-26 12:12:25 +00:00
// This function goes through all infill entities, decides which ones will be used for wiping and
// marks them by the extruder id. Returns volume that remains to be wiped on the wipe tower:
2018-07-18 09:05:39 +00:00
float mark_wiping_extrusions ( const Print & print , unsigned int old_extruder , unsigned int new_extruder , float volume_to_wipe ) ;
2018-06-26 12:12:25 +00:00
2018-07-11 12:46:13 +00:00
void ensure_perimeters_infills_order ( const Print & print ) ;
2018-06-29 10:26:22 +00:00
2018-06-26 12:12:25 +00:00
bool is_overriddable ( const ExtrusionEntityCollection & ee , const PrintConfig & print_config , const PrintObject & object , const PrintRegion & region ) const ;
2020-01-10 10:26:52 +00:00
bool is_overriddable_and_mark ( const ExtrusionEntityCollection & ee , const PrintConfig & print_config , const PrintObject & object , const PrintRegion & region ) {
bool out = this - > is_overriddable ( ee , print_config , object , region ) ;
this - > something_overridable | = out ;
return out ;
}
2018-06-26 12:12:25 +00:00
2018-07-11 12:46:13 +00:00
void set_layer_tools_ptr ( const LayerTools * lt ) { m_layer_tools = lt ; }
2018-06-26 12:12:25 +00:00
private :
2018-07-11 12:46:13 +00:00
int first_nonsoluble_extruder_on_layer ( const PrintConfig & print_config ) const ;
int last_nonsoluble_extruder_on_layer ( const PrintConfig & print_config ) const ;
2018-06-26 12:12:25 +00:00
// This function is called from mark_wiping_extrusions and sets extruder that it should be printed with (-1 .. as usual)
2020-01-14 09:31:18 +00:00
void set_extruder_override ( const ExtrusionEntity * entity , size_t copy_id , int extruder , size_t num_of_copies ) ;
2018-06-26 12:12:25 +00:00
2018-06-20 10:52:00 +00:00
// Returns true in case that entity is not printed with its usual extruder for a given copy:
2019-09-04 12:56:35 +00:00
bool is_entity_overridden ( const ExtrusionEntity * entity , size_t copy_id ) const {
2020-01-10 10:26:52 +00:00
auto it = entity_map . find ( entity ) ;
return it = = entity_map . end ( ) ? false : it - > second [ copy_id ] ! = - 1 ;
2018-06-20 10:52:00 +00:00
}
2020-01-08 13:58:12 +00:00
std : : map < const ExtrusionEntity * , ExtruderPerCopy > entity_map ; // to keep track of who prints what
2020-01-10 10:26:52 +00:00
bool something_overridable = false ;
2018-06-20 10:52:00 +00:00
bool something_overridden = false ;
2018-07-11 12:46:13 +00:00
const LayerTools * m_layer_tools ; // so we know which LayerTools object this belongs to
2018-06-20 10:52:00 +00:00
} ;
2018-06-26 12:12:25 +00:00
class LayerTools
2017-05-16 11:45:28 +00:00
{
2017-05-23 13:00:01 +00:00
public :
2020-01-09 09:32:52 +00:00
LayerTools ( const coordf_t z ) :
2018-06-26 12:12:25 +00:00
print_z ( z ) ,
has_object ( false ) ,
has_support ( false ) ,
2020-01-14 09:31:18 +00:00
extruder_override ( 0 ) ,
2018-06-26 12:12:25 +00:00
has_wipe_tower ( false ) ,
wipe_tower_partitions ( 0 ) ,
wipe_tower_layer_height ( 0. ) { }
2018-07-24 09:20:29 +00:00
// Changing these operators to epsilon version can make a problem in cases where support and object layers get close to each other.
// In case someone tries to do it, make sure you know what you're doing and test it properly (slice multiple objects at once with supports).
bool operator < ( const LayerTools & rhs ) const { return print_z < rhs . print_z ; }
bool operator = = ( const LayerTools & rhs ) const { return print_z = = rhs . print_z ; }
2018-06-26 12:12:25 +00:00
2018-07-13 09:25:22 +00:00
bool is_extruder_order ( unsigned int a , unsigned int b ) const ;
2020-01-08 13:58:12 +00:00
bool has_extruder ( unsigned int extruder ) const { return std : : find ( this - > extruders . begin ( ) , this - > extruders . end ( ) , extruder ) ! = this - > extruders . end ( ) ; }
2018-07-13 09:25:22 +00:00
2020-01-14 09:31:18 +00:00
// Return a zero based extruder from the region, or extruder_override if overriden.
unsigned int perimeter_extruder ( const PrintRegion & region ) const ;
unsigned int infill_extruder ( const PrintRegion & region ) const ;
unsigned int solid_infill_extruder ( const PrintRegion & region ) const ;
// Returns a zero based extruder this eec should be printed with, according to PrintRegion config or extruder_override if overriden.
unsigned int extruder ( const ExtrusionEntityCollection & extrusions , const PrintRegion & region ) const ;
2018-06-26 12:12:25 +00:00
coordf_t print_z ;
bool has_object ;
bool has_support ;
// Zero based extruder IDs, ordered to minimize tool switches.
std : : vector < unsigned int > extruders ;
2020-01-14 09:31:18 +00:00
// If per layer extruder switches are inserted by the G-code preview slider, this value contains the new (1 based) extruder, with which the whole object layer is being printed with.
// If not overriden, it is set to 0.
unsigned int extruder_override ;
2018-06-26 12:12:25 +00:00
// Will there be anything extruded on this layer for the wipe tower?
// Due to the support layers possibly interleaving the object layers,
// wipe tower will be disabled for some support only layers.
bool has_wipe_tower ;
// Number of wipe tower partitions to support the required number of tool switches
// and to support the wipe tower partitions above this one.
size_t wipe_tower_partitions ;
coordf_t wipe_tower_layer_height ;
2018-07-11 12:46:13 +00:00
WipingExtrusions & wiping_extrusions ( ) {
m_wiping_extrusions . set_layer_tools_ptr ( this ) ;
return m_wiping_extrusions ;
}
private :
2018-06-26 12:12:25 +00:00
// This object holds list of extrusion that will be used for extruder wiping
2018-07-11 12:46:13 +00:00
WipingExtrusions m_wiping_extrusions ;
2018-06-26 12:12:25 +00:00
} ;
2017-05-23 13:00:01 +00:00
2018-06-26 12:12:25 +00:00
class ToolOrdering
{
public :
2019-08-16 14:17:37 +00:00
ToolOrdering ( ) { }
// For the use case when each object is printed separately
// (print.config.complete_objects is true).
2020-01-14 09:31:18 +00:00
ToolOrdering ( const PrintObject & object , unsigned int first_extruder , bool prime_multi_material = false ) ;
2019-08-16 14:17:37 +00:00
// For the use case when all objects are printed at once.
// (print.config.complete_objects is false).
2020-01-14 09:31:18 +00:00
ToolOrdering ( const Print & print , unsigned int first_extruder , bool prime_multi_material = false , const std : : vector < std : : pair < double , unsigned int > > * per_layer_extruder_switches = nullptr ) ;
2019-08-16 14:17:37 +00:00
void clear ( ) { m_layer_tools . clear ( ) ; }
// Get the first extruder printing, including the extruder priming areas, returns -1 if there is no layer printed.
unsigned int first_extruder ( ) const { return m_first_printing_extruder ; }
// Get the first extruder printing the layer_tools, returns -1 if there is no layer printed.
unsigned int last_extruder ( ) const { return m_last_printing_extruder ; }
// For a multi-material print, the printing extruders are ordered in the order they shall be primed.
const std : : vector < unsigned int > & all_extruders ( ) const { return m_all_printing_extruders ; }
// Find LayerTools with the closest print_z.
2020-01-07 13:35:43 +00:00
const LayerTools & tools_for_layer ( coordf_t print_z ) const ;
LayerTools & tools_for_layer ( coordf_t print_z ) { return const_cast < LayerTools & > ( std : : as_const ( * this ) . tools_for_layer ( print_z ) ) ; }
2017-05-23 13:00:01 +00:00
2019-08-16 14:17:37 +00:00
const LayerTools & front ( ) const { return m_layer_tools . front ( ) ; }
const LayerTools & back ( ) const { return m_layer_tools . back ( ) ; }
std : : vector < LayerTools > : : const_iterator begin ( ) const { return m_layer_tools . begin ( ) ; }
std : : vector < LayerTools > : : const_iterator end ( ) const { return m_layer_tools . end ( ) ; }
bool empty ( ) const { return m_layer_tools . empty ( ) ; }
std : : vector < LayerTools > & layer_tools ( ) { return m_layer_tools ; }
bool has_wipe_tower ( ) const { return ! m_layer_tools . empty ( ) & & m_first_printing_extruder ! = ( unsigned int ) - 1 & & m_layer_tools . front ( ) . wipe_tower_partitions > 0 ; }
2017-05-23 13:00:01 +00:00
private :
2019-08-16 14:17:37 +00:00
void initialize_layers ( std : : vector < coordf_t > & zs ) ;
2020-01-14 09:31:18 +00:00
void collect_extruders ( const PrintObject & object , const std : : vector < std : : pair < double , unsigned int > > * per_layer_extruder_switches ) ;
2019-08-16 14:17:37 +00:00
void reorder_extruders ( unsigned int last_extruder_id ) ;
void fill_wipe_tower_partitions ( const PrintConfig & config , coordf_t object_bottom_z ) ;
2018-06-26 12:12:25 +00:00
void collect_extruder_statistics ( bool prime_multi_material ) ;
std : : vector < LayerTools > m_layer_tools ;
// First printing extruder, including the multi-material priming sequence.
unsigned int m_first_printing_extruder = ( unsigned int ) - 1 ;
// Final printing extruder.
unsigned int m_last_printing_extruder = ( unsigned int ) - 1 ;
// All extruders, which extrude some material over m_layer_tools.
std : : vector < unsigned int > m_all_printing_extruders ;
const PrintConfig * m_print_config_ptr = nullptr ;
2017-05-23 13:00:01 +00:00
} ;
2017-05-16 11:45:28 +00:00
2018-06-26 12:12:25 +00:00
2017-05-16 11:45:28 +00:00
} // namespace SLic3r
# endif /* slic3r_ToolOrdering_hpp_ */