2017-05-16 13:45:28 +02:00
// Ordering of the tools to minimize tool switches.
#ifndef slic3r_ToolOrdering_hpp_
#define slic3r_ToolOrdering_hpp_
2018-11-26 14:54:23 +01:00
#include "../libslic3r.h"
2017-05-16 13:45:28 +02:00
2020-01-07 14:35:43 +01:00
#include <utility>
2020-01-08 14:58:12 +01:00
#include <boost/container/small_vector.hpp>
2017-05-16 13:45:28 +02:00
namespace Slic3r {
2017-05-25 22:27:53 +02:00
class Print ;
class PrintObject ;
2018-06-26 14:12:25 +02:00
class LayerTools ;
2017-05-25 22:27:53 +02:00
2018-06-20 12:52:00 +02: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 14:12:25 +02:00
public :
2018-06-20 12:52:00 +02: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 14:58:12 +01: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 14:12:25 +02:00
// This is called from GCode::process_layer - see implementation for further comments:
2020-01-08 14:58:12 +01:00
const ExtruderPerCopy * get_extruder_overrides ( const ExtrusionEntity * entity , int correct_extruder_id , size_t num_of_copies );
2018-06-26 14:12:25 +02: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 11:05:39 +02:00
float mark_wiping_extrusions ( const Print & print , unsigned int old_extruder , unsigned int new_extruder , float volume_to_wipe );
2018-06-26 14:12:25 +02:00
2018-07-11 14:46:13 +02:00
void ensure_perimeters_infills_order ( const Print & print );
2018-06-29 12:26:22 +02:00
2018-06-26 14:12:25 +02:00
bool is_overriddable ( const ExtrusionEntityCollection & ee , const PrintConfig & print_config , const PrintObject & object , const PrintRegion & region ) const ;
2020-01-10 11:26:52 +01: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 14:12:25 +02:00
2018-07-11 14:46:13 +02:00
void set_layer_tools_ptr ( const LayerTools * lt ) { m_layer_tools = lt ; }
2018-06-26 14:12:25 +02:00
private :
2018-07-11 14:46:13 +02: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 14:12:25 +02:00
// This function is called from mark_wiping_extrusions and sets extruder that it should be printed with (-1 .. as usual)
2020-01-14 10:31:18 +01:00
void set_extruder_override ( const ExtrusionEntity * entity , size_t copy_id , int extruder , size_t num_of_copies );
2018-06-26 14:12:25 +02:00
2018-06-20 12:52:00 +02:00
// Returns true in case that entity is not printed with its usual extruder for a given copy:
2019-09-04 14:56:35 +02:00
bool is_entity_overridden ( const ExtrusionEntity * entity , size_t copy_id ) const {
2020-01-10 11:26:52 +01:00
auto it = entity_map . find ( entity );
return it == entity_map . end () ? false : it -> second [ copy_id ] != - 1 ;
2018-06-20 12:52:00 +02:00
}
2020-01-08 14:58:12 +01:00
std :: map < const ExtrusionEntity * , ExtruderPerCopy > entity_map ; // to keep track of who prints what
2020-01-10 11:26:52 +01:00
bool something_overridable = false ;
2018-06-20 12:52:00 +02:00
bool something_overridden = false ;
2018-07-11 14:46:13 +02:00
const LayerTools * m_layer_tools ; // so we know which LayerTools object this belongs to
2018-06-20 12:52:00 +02:00
};
2018-06-26 14:12:25 +02:00
class LayerTools
2017-05-16 13:45:28 +02:00
{
2017-05-23 15:00:01 +02:00
public :
2020-01-09 10:32:52 +01:00
LayerTools ( const coordf_t z ) :
2018-06-26 14:12:25 +02:00
print_z ( z ),
has_object ( false ),
has_support ( false ),
2020-01-14 10:31:18 +01:00
extruder_override ( 0 ),
2018-06-26 14:12:25 +02:00
has_wipe_tower ( false ),
wipe_tower_partitions ( 0 ),
wipe_tower_layer_height ( 0. ) {}
2017-05-16 13:45:28 +02:00
2018-07-24 11:20:29 +02: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 ; }
2017-05-16 13:45:28 +02:00
2018-07-13 11:25:22 +02:00
bool is_extruder_order ( unsigned int a , unsigned int b ) const ;
2020-01-08 14:58:12 +01:00
bool has_extruder ( unsigned int extruder ) const { return std :: find ( this -> extruders . begin (), this -> extruders . end (), extruder ) != this -> extruders . end (); }
2018-07-13 11:25:22 +02:00
2020-01-14 10:31:18 +01: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 14:12:25 +02: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 10:31:18 +01: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 14:12:25 +02: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 14:46:13 +02:00
WipingExtrusions & wiping_extrusions () {
m_wiping_extrusions . set_layer_tools_ptr ( this );
return m_wiping_extrusions ;
}
private :
2018-06-26 14:12:25 +02:00
// This object holds list of extrusion that will be used for extruder wiping
2018-07-11 14:46:13 +02:00
WipingExtrusions m_wiping_extrusions ;
2018-06-26 14:12:25 +02:00
};
2018-06-20 12:52:00 +02:00
2017-05-23 15:00:01 +02:00
2018-06-26 14:12:25 +02:00
class ToolOrdering
{
public :
2019-08-16 16:17:37 +02:00
ToolOrdering () {}
2017-05-23 15:00:01 +02:00
2019-08-16 16:17:37 +02:00
// For the use case when each object is printed separately
// (print.config.complete_objects is true).
2020-01-14 10:31:18 +01:00
ToolOrdering ( const PrintObject & object , unsigned int first_extruder , bool prime_multi_material = false );
2017-05-23 15:00:01 +02:00
2019-08-16 16:17:37 +02:00
// For the use case when all objects are printed at once.
// (print.config.complete_objects is false).
2020-01-14 10:31:18 +01: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 );
2017-05-23 15:00:01 +02:00
2019-08-16 16:17:37 +02:00
void clear () { m_layer_tools . clear (); }
2017-05-25 22:27:53 +02:00
2019-08-16 16:17:37 +02:00
// 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 ; }
2017-05-23 15:00:01 +02:00
2019-08-16 16:17:37 +02:00
// 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 ; }
2017-09-01 17:30:18 +02:00
2019-08-16 16:17:37 +02:00
// 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 ; }
2017-05-23 15:00:01 +02:00
2019-08-16 16:17:37 +02:00
// Find LayerTools with the closest print_z.
2020-01-07 14:35:43 +01: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 )); }
2019-08-16 16:17:37 +02: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 15:00:01 +02:00
private :
2019-08-16 16:17:37 +02:00
void initialize_layers ( std :: vector < coordf_t > & zs );
2020-01-14 10:31:18 +01:00
void collect_extruders ( const PrintObject & object , const std :: vector < std :: pair < double , unsigned int >> * per_layer_extruder_switches );
2019-08-16 16:17:37 +02: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 14:12:25 +02:00
void collect_extruder_statistics ( bool prime_multi_material );
2017-05-23 15:00:01 +02:00
2018-06-26 14:12:25 +02:00
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-16 13:45:28 +02:00
};
2018-06-26 14:12:25 +02:00
2017-05-16 13:45:28 +02:00
} // namespace SLic3r
#endif /* slic3r_ToolOrdering_hpp_ */