2013-12-20 01:36:42 +01:00
#ifndef slic3r_Print_hpp_
#define slic3r_Print_hpp_
2018-11-08 14:23:17 +01:00
#include "PrintBase.hpp"
2014-11-30 21:58:41 +01:00
#include "BoundingBox.hpp"
2020-05-26 11:09:38 +02:00
#include "ExtrusionEntityCollection.hpp"
2014-08-03 19:17:23 +02:00
#include "Flow.hpp"
2014-05-06 11:07:18 +03:00
#include "Point.hpp"
2016-12-12 17:53:38 +01:00
#include "Slicing.hpp"
2017-05-25 22:27:53 +02:00
#include "GCode/ToolOrdering.hpp"
#include "GCode/WipeTower.hpp"
2019-11-22 12:39:03 +01:00
#include "GCode/ThumbnailData.hpp"
2020-03-02 15:13:23 +01:00
#include "GCode/GCodeProcessor.hpp"
2013-12-20 01:36:42 +01:00
2020-01-10 11:26:52 +01:00
#include "libslic3r.h"
2013-12-20 01:36:42 +01:00
namespace Slic3r {
2014-05-06 11:07:18 +03:00
class Print ;
2014-08-03 19:17:23 +02:00
class PrintObject ;
2014-05-06 11:07:18 +03:00
class ModelObject ;
2018-03-28 17:05:31 +02:00
class GCode ;
2020-02-08 21:36:29 +01:00
enum class SlicingMode : uint32_t ;
2020-05-26 11:09:38 +02:00
class Layer ;
class SupportLayer ;
2014-05-06 11:07:18 +03:00
2020-09-18 10:53:50 +02:00
namespace FillAdaptive {
2020-09-02 22:53:10 +02:00
struct Octree ;
2020-09-17 18:39:28 +02:00
struct OctreeDeleter ;
using OctreePtr = std :: unique_ptr < Octree , OctreeDeleter > ;
2020-09-02 22:53:10 +02:00
};
2020-08-26 16:51:34 +02:00
2016-09-13 13:30:00 +02:00
// Print step IDs for keeping track of the print state.
2020-10-21 14:00:42 +02:00
// The Print steps are applied in this order.
2013-12-20 01:36:42 +01:00
enum PrintStep {
2020-01-15 16:20:16 +01:00
psWipeTower ,
2020-10-21 14:00:42 +02:00
// Ordering of the tools on PrintObjects for a multi-material print.
2020-01-15 16:20:16 +01:00
// psToolOrdering is a synonym to psWipeTower, as the Wipe Tower calculates and modifies the ToolOrdering,
// while if printing without the Wipe Tower, the ToolOrdering is calculated as well.
psToolOrdering = psWipeTower ,
2020-10-21 14:00:42 +02:00
psSkirt ,
psBrim ,
// Last step before G-code export, after this step is finished, the initial extrusion path preview
// should be refreshed.
psSlicingFinished = psBrim ,
2020-01-15 16:20:16 +01:00
psGCodeExport ,
psCount ,
2014-06-11 00:15:02 +02:00
};
2020-01-15 16:20:16 +01:00
2014-06-11 00:15:02 +02:00
enum PrintObjectStep {
posSlice , posPerimeters , posPrepareInfill ,
2020-04-14 11:53:28 +02:00
posInfill , posIroning , posSupportMaterial , posCount ,
2013-12-20 01:36:42 +01:00
};
2014-05-06 11:07:18 +03:00
// A PrintRegion object represents a group of volumes to print
// sharing the same config (including the same assigned extruder(s))
class PrintRegion
{
friend class Print ;
2018-09-11 14:04:47 +02:00
// Methods NOT modifying the PrintRegion's state:
2017-03-28 13:25:10 +02:00
public :
2018-09-11 14:04:47 +02:00
const Print * print () const { return m_print ; }
const PrintRegionConfig & config () const { return m_config ; }
2019-09-04 16:11:16 +02:00
// 1-based extruder identifier for this region and role.
unsigned int extruder ( FlowRole role ) const ;
2018-09-11 14:04:47 +02:00
Flow flow ( FlowRole role , double layer_height , bool bridge , bool first_layer , double width , const PrintObject & object ) const ;
2018-09-17 15:12:13 +02:00
// Average diameter of nozzles participating on extruding this region.
2018-09-11 14:04:47 +02:00
coordf_t nozzle_dmr_avg ( const PrintConfig & print_config ) const ;
2018-09-17 15:12:13 +02:00
// Average diameter of nozzles participating on extruding this region.
2018-10-18 14:36:46 +02:00
coordf_t bridging_height_avg ( const PrintConfig & print_config ) const ;
2014-05-06 11:07:18 +03:00
2020-01-14 15:12:45 +01:00
// Collect 0-based extruder indices used to print this region's object.
2019-01-21 10:06:51 +01:00
void collect_object_printing_extruders ( std :: vector < unsigned int > & object_extruders ) const ;
2021-02-03 15:12:53 +01:00
static void collect_object_printing_extruders ( const PrintConfig & print_config , const PrintRegionConfig & region_config , const bool has_brim , std :: vector < unsigned int > & object_extruders );
2019-01-21 10:06:51 +01:00
2018-09-11 14:04:47 +02:00
// Methods modifying the PrintRegion's state:
public :
Print * print () { return m_print ; }
2018-10-18 14:36:46 +02:00
void set_config ( const PrintRegionConfig & config ) { m_config = config ; }
void set_config ( PrintRegionConfig && config ) { m_config = std :: move ( config ); }
void config_apply_only ( const ConfigBase & other , const t_config_option_keys & keys , bool ignore_nonexistent = false )
{ this -> m_config . apply_only ( other , keys , ignore_nonexistent ); }
protected :
size_t m_refcnt ;
2014-05-06 11:07:18 +03:00
2017-03-28 13:25:10 +02:00
private :
2018-09-11 14:04:47 +02:00
Print * m_print ;
PrintRegionConfig m_config ;
2015-05-31 22:04:32 +02:00
2018-10-18 14:36:46 +02:00
PrintRegion ( Print * print ) : m_refcnt ( 0 ), m_print ( print ) {}
PrintRegion ( Print * print , const PrintRegionConfig & config ) : m_refcnt ( 0 ), m_print ( print ), m_config ( config ) {}
2020-02-07 14:10:18 +01:00
~ PrintRegion () = default ;
2014-05-06 11:07:18 +03:00
};
2021-02-03 15:12:53 +01:00
template < typename T >
class ConstVectorOfPtrsAdaptor {
public :
// Returning a non-const pointer to const pointers to T.
T * const * begin () const { return m_data -> data (); }
T * const * end () const { return m_data -> data () + m_data -> size (); }
const T * front () const { return m_data -> front (); }
const T * back () const { return m_data -> front (); }
size_t size () const { return m_data -> size (); }
bool empty () const { return m_data -> empty (); }
const T * operator []( size_t i ) const { return ( * m_data )[ i ]; }
const T * at ( size_t i ) const { return m_data -> at ( i ); }
std :: vector < const T *> vector () const { return std :: vector < const T *> ( this -> begin (), this -> end ()); }
protected :
ConstVectorOfPtrsAdaptor ( const std :: vector < T *> * data ) : m_data ( data ) {}
private :
const std :: vector < T *> * m_data ;
};
typedef std :: vector < Layer *> LayerPtrs ;
typedef std :: vector < const Layer *> ConstLayerPtrs ;
class ConstLayerPtrsAdaptor : public ConstVectorOfPtrsAdaptor < Layer > {
friend PrintObject ;
ConstLayerPtrsAdaptor ( const LayerPtrs * data ) : ConstVectorOfPtrsAdaptor < Layer > ( data ) {}
};
typedef std :: vector < SupportLayer *> SupportLayerPtrs ;
typedef std :: vector < const SupportLayer *> ConstSupportLayerPtrs ;
class ConstSupportLayerPtrsAdaptor : public ConstVectorOfPtrsAdaptor < SupportLayer > {
friend PrintObject ;
ConstSupportLayerPtrsAdaptor ( const SupportLayerPtrs * data ) : ConstVectorOfPtrsAdaptor < SupportLayer > ( data ) {}
};
2014-05-06 11:07:18 +03:00
class BoundingBoxf3 ; // TODO: for temporary constructor parameter
2020-01-23 09:53:06 +01:00
// Single instance of a PrintObject.
// As multiple PrintObjects may be generated for a single ModelObject (their instances differ in rotation around Z),
// ModelObject's instancess will be distributed among these multiple PrintObjects.
struct PrintInstance
{
// Parent PrintObject
PrintObject * print_object ;
// Source ModelInstance of a ModelObject, for which this print_object was created.
const ModelInstance * model_instance ;
2020-02-07 14:10:18 +01:00
// Shift of this instance's center into the world coordinates.
2020-01-23 09:53:06 +01:00
Point shift ;
};
typedef std :: vector < PrintInstance > PrintInstances ;
2018-11-08 14:23:17 +01:00
class PrintObject : public PrintObjectBaseWithState < Print , PrintObjectStep , posCount >
2014-05-06 11:07:18 +03:00
{
2018-11-08 14:23:17 +01:00
private : // Prevents erroneous use by other classes.
typedef PrintObjectBaseWithState < Print , PrintObjectStep , posCount > Inherited ;
2014-05-06 11:07:18 +03:00
2016-10-13 16:00:22 +02:00
public :
2019-06-20 16:15:09 +02:00
// vector of (layer height ranges and vectors of volume ids), indexed by region_id
std :: vector < std :: vector < std :: pair < t_layer_height_range , int >>> region_volumes ;
2016-12-12 17:53:38 +01:00
2020-02-07 14:10:18 +01:00
// Size of an object: XYZ in scaled coordinates. The size might not be quite snug in XY plane.
2021-02-03 15:12:53 +01:00
const Vec3crd & size () const { return m_size ; }
const PrintObjectConfig & config () const { return m_config ; }
ConstLayerPtrsAdaptor layers () const { return ConstLayerPtrsAdaptor ( & m_layers ); }
ConstSupportLayerPtrsAdaptor support_layers () const { return ConstSupportLayerPtrsAdaptor ( & m_support_layers ); }
const Transform3d & trafo () const { return m_trafo ; }
const PrintInstances & instances () const { return m_instances ; }
// Whoever will get a non-const pointer to PrintObject will be able to modify its layers.
LayerPtrs & layers () { return m_layers ; }
SupportLayerPtrs & support_layers () { return m_support_layers ; }
2018-10-18 14:36:46 +02:00
2020-02-07 14:10:18 +01:00
// Bounding box is used to align the object infill patterns, and to calculate attractor for the rear seam.
// The bounding box may not be quite snug.
BoundingBox bounding_box () const { return BoundingBox ( Point ( - m_size . x () / 2 , - m_size . y () / 2 ), Point ( m_size . x () / 2 , m_size . y () / 2 )); }
// Height is used for slicing, for sorting the objects by height for sequential printing and for checking vertical clearence in sequential print mode.
// The height is snug.
coord_t height () const { return m_size . z (); }
// Centering offset of the sliced mesh from the scaled and rotated mesh of the model.
const Point & center_offset () const { return m_center_offset ; }
2014-05-06 11:07:18 +03:00
2017-05-30 17:24:50 +02:00
// adds region_id, too, if necessary
2019-06-20 16:15:09 +02:00
void add_region_volume ( unsigned int region_id , int volume_id , const t_layer_height_range & layer_range ) {
2017-05-31 12:55:59 +02:00
if ( region_id >= region_volumes . size ())
2018-12-17 19:46:36 +01:00
region_volumes . resize ( region_id + 1 );
2019-06-20 16:15:09 +02:00
region_volumes [ region_id ]. emplace_back ( layer_range , volume_id );
2017-05-31 12:55:59 +02:00
}
2017-05-30 17:24:50 +02:00
// This is the *total* layer count (including support layers)
// this value is not supposed to be compared with Layer::id
// since they have different semantics.
2020-01-23 09:53:06 +01:00
size_t total_layer_count () const { return this -> layer_count () + this -> support_layer_count (); }
size_t layer_count () const { return m_layers . size (); }
void clear_layers ();
2020-01-10 11:26:52 +01:00
const Layer * get_layer ( int idx ) const { return m_layers [ idx ]; }
Layer * get_layer ( int idx ) { return m_layers [ idx ]; }
// Get a layer exactly at print_z.
2020-05-26 11:09:38 +02:00
const Layer * get_layer_at_printz ( coordf_t print_z ) const ;
Layer * get_layer_at_printz ( coordf_t print_z );
2020-01-10 11:26:52 +01:00
// Get a layer approximately at print_z.
2020-05-26 11:09:38 +02:00
const Layer * get_layer_at_printz ( coordf_t print_z , coordf_t epsilon ) const ;
Layer * get_layer_at_printz ( coordf_t print_z , coordf_t epsilon );
2020-12-15 06:46:44 +01:00
// Get the first layer approximately bellow print_z.
const Layer * get_first_layer_bellow_printz ( coordf_t print_z , coordf_t epsilon ) const ;
2016-10-16 16:30:56 +02:00
2016-09-13 13:30:00 +02:00
// print_z: top of the layer; slice_z: center of the layer.
2014-06-10 16:01:57 +02:00
Layer * add_layer ( int id , coordf_t height , coordf_t print_z , coordf_t slice_z );
2014-05-06 11:07:18 +03:00
2018-09-11 14:04:47 +02:00
size_t support_layer_count () const { return m_support_layers . size (); }
2014-05-06 11:07:18 +03:00
void clear_support_layers ();
2018-09-11 14:04:47 +02:00
SupportLayer * get_support_layer ( int idx ) { return m_support_layers [ idx ]; }
2015-01-30 18:45:30 +01:00
SupportLayer * add_support_layer ( int id , coordf_t height , coordf_t print_z );
2021-02-03 15:12:53 +01:00
SupportLayerPtrs :: iterator insert_support_layer ( SupportLayerPtrs :: iterator pos , size_t id , coordf_t height , coordf_t print_z , coordf_t slice_z );
2014-05-06 11:07:18 +03:00
void delete_support_layer ( int idx );
2014-06-11 00:15:02 +02:00
2019-01-21 10:06:51 +01:00
// Initialize the layer_height_profile from the model_object's layer_height_profile, from model_object's layer height table, or from slicing parameters.
// Returns true, if the layer_height_profile was changed.
static bool update_layer_height_profile ( const ModelObject & model_object , const SlicingParameters & slicing_parameters , std :: vector < coordf_t > & layer_height_profile );
2018-05-30 15:18:45 +02:00
2016-12-12 17:53:38 +01:00
// Collect the slicing parameters, to be used by variable layer thickness algorithm,
// by the interactive layer height editor and by the printing process itself.
// The slicing parameters are dependent on various configuration values
// (layer height, first layer height, raft settings, print nozzle diameter etc).
2019-03-05 14:05:58 +01:00
const SlicingParameters & slicing_parameters () const { return m_slicing_params ; }
2019-04-13 14:15:54 +02:00
static SlicingParameters slicing_parameters ( const DynamicPrintConfig & full_config , const ModelObject & model_object , float object_max_z );
2019-01-21 10:06:51 +01:00
// returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
std :: vector < unsigned int > object_extruders () const ;
2016-12-12 17:53:38 +01:00
2020-12-11 12:21:07 +01:00
// Called by make_perimeters()
2018-03-23 11:41:20 +01:00
void slice ();
2018-03-23 16:00:00 +01:00
2018-09-17 15:12:13 +02:00
// Helpers to slice support enforcer / blocker meshes by the support generator.
2019-06-20 16:15:09 +02:00
std :: vector < ExPolygons > slice_support_volumes ( const ModelVolumeType & model_volume_type ) const ;
std :: vector < ExPolygons > slice_support_blockers () const { return this -> slice_support_volumes ( ModelVolumeType :: SUPPORT_BLOCKER ); }
std :: vector < ExPolygons > slice_support_enforcers () const { return this -> slice_support_volumes ( ModelVolumeType :: SUPPORT_ENFORCER ); }
2018-09-17 15:12:13 +02:00
2020-08-31 07:25:43 +02:00
// Helpers to project custom facets on slices
void project_and_append_custom_facets ( bool seam , EnforcerBlockerType type , std :: vector < ExPolygons >& expolys ) const ;
2020-04-21 13:50:47 +02:00
2020-01-23 09:53:06 +01:00
private :
2018-11-08 14:23:17 +01:00
// to be called from Print only.
friend class Print ;
2020-02-07 14:10:18 +01:00
PrintObject ( Print * print , ModelObject * model_object , const Transform3d & trafo , PrintInstances && instances );
~ PrintObject () = default ;
2018-11-08 14:23:17 +01:00
void config_apply ( const ConfigBase & other , bool ignore_nonexistent = false ) { this -> m_config . apply ( other , ignore_nonexistent ); }
void config_apply_only ( const ConfigBase & other , const t_config_option_keys & keys , bool ignore_nonexistent = false ) { this -> m_config . apply_only ( other , keys , ignore_nonexistent ); }
2020-01-23 09:53:06 +01:00
PrintBase :: ApplyStatus set_instances ( PrintInstances && instances );
2018-11-08 14:23:17 +01:00
// Invalidates the step, and its depending steps in PrintObject and Print.
bool invalidate_step ( PrintObjectStep step );
2018-11-12 16:28:27 +01:00
// Invalidates all PrintObject and Print steps.
bool invalidate_all_steps ();
2018-11-21 17:35:35 +01:00
// Invalidate steps based on a set of parameters changed.
2021-02-11 12:03:21 +01:00
// It may be called for both the PrintObjectConfig and PrintRegionConfig.
bool invalidate_state_by_config_options (
const ConfigOptionResolver & old_config , const ConfigOptionResolver & new_config , const std :: vector < t_config_option_key > & opt_keys );
2019-03-05 14:05:58 +01:00
// If ! m_slicing_params.valid, recalculate.
void update_slicing_parameters ();
2018-11-08 14:23:17 +01:00
2019-01-21 10:06:51 +01:00
static PrintObjectConfig object_config_from_model_object ( const PrintObjectConfig & default_object_config , const ModelObject & object , size_t num_extruders );
2019-06-20 16:15:09 +02:00
static PrintRegionConfig region_config_from_model_volume ( const PrintRegionConfig & default_region_config , const DynamicPrintConfig * layer_range_config , const ModelVolume & volume , size_t num_extruders );
2019-01-21 10:06:51 +01:00
2018-03-23 16:00:00 +01:00
private :
2018-03-23 11:41:20 +01:00
void make_perimeters ();
void prepare_infill ();
void infill ();
2020-04-14 11:53:28 +02:00
void ironing ();
2018-03-23 11:41:20 +01:00
void generate_support_material ();
2019-01-23 14:00:03 +01:00
void _slice ( const std :: vector < coordf_t > & layer_height_profile );
2017-03-08 11:56:42 +01:00
std :: string _fix_slicing_errors ();
2020-01-03 14:05:56 +01:00
void simplify_slices ( double distance );
2015-03-06 09:56:58 +01:00
bool has_support_material () const ;
2016-11-10 19:23:01 +01:00
void detect_surfaces_type ();
2015-10-26 23:23:03 +01:00
void process_external_surfaces ();
2016-09-26 13:56:24 +02:00
void discover_vertical_shells ();
2014-12-24 10:20:55 +01:00
void bridge_over_infill ();
2017-08-02 14:24:32 +02:00
void clip_fill_surfaces ();
void discover_horizontal_shells ();
void combine_infill ();
2016-12-20 12:19:13 +01:00
void _generate_support_material ();
2020-09-18 10:53:50 +02:00
std :: pair < FillAdaptive :: OctreePtr , FillAdaptive :: OctreePtr > prepare_adaptive_infill_data ();
2016-12-12 17:53:38 +01:00
2020-01-30 12:22:22 +01:00
// XYZ in scaled coordinates
Vec3crd m_size ;
2018-09-11 14:04:47 +02:00
PrintObjectConfig m_config ;
2018-10-17 11:12:38 +02:00
// Translation in Z + Rotation + Scaling / Mirroring.
Transform3d m_trafo = Transform3d :: Identity ();
2018-09-11 14:04:47 +02:00
// Slic3r::Point objects in scaled G-code coordinates
2020-01-23 09:53:06 +01:00
std :: vector < PrintInstance > m_instances ;
2020-02-07 14:10:18 +01:00
// The mesh is being centered before thrown to Clipper, so that the Clipper's fixed coordinates require less bits.
// This is the adjustment of the the Object's coordinate system towards PrintObject's coordinate system.
Point m_center_offset ;
2018-09-11 14:04:47 +02:00
2019-03-04 15:28:04 +01:00
SlicingParameters m_slicing_params ;
2018-09-11 14:04:47 +02:00
LayerPtrs m_layers ;
SupportLayerPtrs m_support_layers ;
2014-05-19 23:38:10 +03:00
2020-02-07 14:10:18 +01:00
// this is set to true when LayerRegion->slices is split in top/internal/bottom
// so that next call to make_perimeters() performs a union() before computing loops
bool m_typed_slices = false ;
2020-12-09 14:07:22 +01:00
std :: vector < ExPolygons > slice_region ( size_t region_id , const std :: vector < float > & z , SlicingMode mode , size_t slicing_mode_normal_below_layer , SlicingMode mode_below ) const ;
std :: vector < ExPolygons > slice_region ( size_t region_id , const std :: vector < float > & z , SlicingMode mode ) const
{ return this -> slice_region ( region_id , z , mode , 0 , mode ); }
2019-06-20 16:15:09 +02:00
std :: vector < ExPolygons > slice_modifiers ( size_t region_id , const std :: vector < float > & z ) const ;
2020-12-09 14:07:22 +01:00
std :: vector < ExPolygons > slice_volumes (
const std :: vector < float > & z ,
SlicingMode mode , size_t slicing_mode_normal_below_layer , SlicingMode mode_below ,
const std :: vector < const ModelVolume *> & volumes ) const ;
std :: vector < ExPolygons > slice_volumes ( const std :: vector < float > & z , SlicingMode mode , const std :: vector < const ModelVolume *> & volumes ) const
{ return this -> slice_volumes ( z , mode , 0 , mode , volumes ); }
2020-02-08 21:36:29 +01:00
std :: vector < ExPolygons > slice_volume ( const std :: vector < float > & z , SlicingMode mode , const ModelVolume & volume ) const ;
std :: vector < ExPolygons > slice_volume ( const std :: vector < float > & z , const std :: vector < t_layer_height_range > & ranges , SlicingMode mode , const ModelVolume & volume ) const ;
2014-05-06 11:07:18 +03:00
};
2018-09-11 14:04:47 +02:00
struct WipeTowerData
{
// Following section will be consumed by the GCodeGenerator.
// Tool ordering of a non-sequential print has to be known to calculate the wipe tower.
// Cache it here, so it does not need to be recalculated during the G-code generation.
2020-01-16 14:59:16 +01:00
ToolOrdering & tool_ordering ;
2018-09-11 14:04:47 +02:00
// Cache of tool changes per print layer.
2019-06-14 12:28:24 +02:00
std :: unique_ptr < std :: vector < WipeTower :: ToolChangeResult >> priming ;
2018-09-11 14:04:47 +02:00
std :: vector < std :: vector < WipeTower :: ToolChangeResult >> tool_changes ;
std :: unique_ptr < WipeTower :: ToolChangeResult > final_purge ;
2018-09-17 15:12:13 +02:00
std :: vector < float > used_filament ;
int number_of_toolchanges ;
2018-09-11 14:04:47 +02:00
2018-09-12 11:59:02 +02:00
// Depth of the wipe tower to pass to GLCanvas3D for exact bounding box:
float depth ;
2019-10-08 13:50:51 +02:00
float brim_width ;
2018-09-12 11:59:02 +02:00
2018-09-11 14:04:47 +02:00
void clear () {
priming . reset ( nullptr );
tool_changes . clear ();
final_purge . reset ( nullptr );
2018-09-17 15:12:13 +02:00
used_filament . clear ();
number_of_toolchanges = - 1 ;
2018-09-12 11:59:02 +02:00
depth = 0.f ;
2019-10-08 13:50:51 +02:00
brim_width = 0.f ;
2018-09-11 14:04:47 +02:00
}
2020-01-16 14:59:16 +01:00
private :
// Only allow the WipeTowerData to be instantiated internally by Print,
// as this WipeTowerData shares reference to Print::m_tool_ordering.
friend class Print ;
WipeTowerData ( ToolOrdering & tool_ordering ) : tool_ordering ( tool_ordering ) { clear (); }
WipeTowerData ( const WipeTowerData & /* rhs */ ) = delete ;
WipeTowerData & operator = ( const WipeTowerData & /* rhs */ ) = delete ;
2018-09-11 14:04:47 +02:00
};
struct PrintStatistics
{
PrintStatistics () { clear (); }
2020-07-16 11:09:21 +02:00
std :: string estimated_normal_print_time ;
std :: string estimated_silent_print_time ;
2018-09-11 14:04:47 +02:00
double total_used_filament ;
double total_extruded_volume ;
double total_cost ;
2019-02-04 18:55:06 -05:00
int total_toolchanges ;
2018-09-11 14:04:47 +02:00
double total_weight ;
2018-09-17 15:12:13 +02:00
double total_wipe_tower_cost ;
double total_wipe_tower_filament ;
2018-09-11 14:04:47 +02:00
std :: map < size_t , float > filament_stats ;
2018-12-12 15:09:20 +01:00
// Config with the filled in print statistics.
DynamicConfig config () const ;
// Config with the statistics keys populated with placeholder strings.
static DynamicConfig placeholders ();
// Replace the print statistics placeholders in the path.
std :: string finalize_output_path ( const std :: string & path_in ) const ;
2018-09-11 14:04:47 +02:00
void clear () {
total_used_filament = 0. ;
total_extruded_volume = 0. ;
total_cost = 0. ;
2019-02-04 18:55:06 -05:00
total_toolchanges = 0 ;
2018-09-12 11:59:02 +02:00
total_weight = 0. ;
2018-09-17 15:12:13 +02:00
total_wipe_tower_cost = 0. ;
total_wipe_tower_filament = 0. ;
2018-09-11 14:04:47 +02:00
filament_stats . clear ();
}
};
2021-02-03 15:12:53 +01:00
typedef std :: vector < PrintObject *> PrintObjectPtrs ;
typedef std :: vector < const PrintObject *> ConstPrintObjectPtrs ;
class ConstPrintObjectPtrsAdaptor : public ConstVectorOfPtrsAdaptor < PrintObject > {
friend Print ;
ConstPrintObjectPtrsAdaptor ( const PrintObjectPtrs * data ) : ConstVectorOfPtrsAdaptor < PrintObject > ( data ) {}
};
typedef std :: vector < PrintRegion *> PrintRegionPtrs ;
typedef std :: vector < const PrintRegion *> ConstPrintRegionPtrs ;
class ConstPrintRegionPtrsAdaptor : public ConstVectorOfPtrsAdaptor < PrintRegion > {
friend Print ;
ConstPrintRegionPtrsAdaptor ( const PrintRegionPtrs * data ) : ConstVectorOfPtrsAdaptor < PrintRegion > ( data ) {}
};
2014-05-06 11:07:18 +03:00
2016-09-13 13:30:00 +02:00
// The complete print tray with possibly multiple objects.
2018-11-08 14:23:17 +01:00
class Print : public PrintBaseWithState < PrintStep , psCount >
2014-05-06 11:07:18 +03:00
{
2018-11-08 14:23:17 +01:00
private : // Prevents erroneous use by other classes.
typedef PrintBaseWithState < PrintStep , psCount > Inherited ;
2021-02-03 15:12:53 +01:00
// Bool indicates if supports of PrintObject are top-level contour.
typedef std :: pair < PrintObject * , bool > PrintObjectInfo ;
2018-11-08 14:23:17 +01:00
2017-03-13 16:03:11 +01:00
public :
2020-02-07 14:10:18 +01:00
Print () = default ;
2018-11-08 14:23:17 +01:00
virtual ~ Print () { this -> clear (); }
2020-03-04 13:06:21 +01:00
PrinterTechnology technology () const noexcept override { return ptFFF ; }
2017-03-13 16:03:11 +01:00
2018-09-11 14:04:47 +02:00
// Methods, which change the state of Print / PrintObject / PrintRegion.
// The following methods are synchronized with process() and export_gcode(),
// so that process() and export_gcode() may be called from a background thread.
// In case the following methods need to modify data processed by process() or export_gcode(),
// a cancellation callback is executed to stop the background processing before the operation.
2018-11-08 14:23:17 +01:00
void clear () override ;
2018-11-08 20:18:40 +01:00
bool empty () const override { return m_objects . empty (); }
2020-10-14 16:48:56 +02:00
// List of existing PrintObject IDs, to remove notifications for non-existent IDs.
std :: vector < ObjectID > print_object_ids () const override ;
2018-11-08 14:23:17 +01:00
2019-07-25 14:39:19 +02:00
ApplyStatus apply ( const Model & model , DynamicPrintConfig config ) override ;
2018-11-08 14:23:17 +01:00
2018-11-08 20:18:40 +01:00
void process () override ;
2019-03-13 15:44:50 +01:00
// Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
// If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
2020-05-07 10:49:12 +02:00
std :: string export_gcode ( const std :: string & path_template , GCodeProcessor :: Result * result , ThumbnailsGeneratorCallback thumbnail_cb = nullptr );
2017-03-13 16:03:11 +01:00
2014-06-11 00:15:02 +02:00
// methods for handling state
2018-11-08 14:23:17 +01:00
bool is_step_done ( PrintStep step ) const { return Inherited :: is_step_done ( step ); }
2018-12-11 17:49:31 +01:00
// Returns true if an object step is done on all objects and there's at least one object.
2018-09-11 14:04:47 +02:00
bool is_step_done ( PrintObjectStep step ) const ;
2018-12-11 17:49:31 +01:00
// Returns true if the last step was finished with success.
bool finished () const override { return this -> is_step_done ( psGCodeExport ); }
2018-03-28 17:05:31 +02:00
2018-09-11 14:04:47 +02:00
bool has_infinite_skirt () const ;
bool has_skirt () const ;
2021-02-03 15:12:53 +01:00
bool has_brim () const ;
2018-09-12 11:59:02 +02:00
2016-11-05 02:23:46 +01:00
// Returns an empty string if valid, otherwise returns an error message.
2018-11-08 20:18:40 +01:00
std :: string validate () const override ;
2018-09-11 14:04:47 +02:00
double skirt_first_layer_height () const ;
Flow brim_flow () const ;
Flow skirt_flow () const ;
2014-08-03 18:41:09 +02:00
2017-05-03 18:28:22 +02:00
std :: vector < unsigned int > object_extruders () const ;
std :: vector < unsigned int > support_material_extruders () const ;
std :: vector < unsigned int > extruders () const ;
2018-09-11 14:04:47 +02:00
double max_allowed_layer_height () const ;
bool has_support_material () const ;
// Make sure the background processing has no access to this model_object during this call!
void auto_assign_extruders ( ModelObject * model_object ) const ;
2017-02-15 11:05:52 +01:00
2018-09-11 14:04:47 +02:00
const PrintConfig & config () const { return m_config ; }
const PrintObjectConfig & default_object_config () const { return m_default_object_config ; }
const PrintRegionConfig & default_region_config () const { return m_default_region_config ; }
2021-02-03 15:12:53 +01:00
ConstPrintObjectPtrsAdaptor objects () const { return ConstPrintObjectPtrsAdaptor ( & m_objects ); }
PrintObject * get_object ( size_t idx ) { return const_cast < PrintObject *> ( m_objects [ idx ]); }
2018-10-11 10:03:38 +02:00
const PrintObject * get_object ( size_t idx ) const { return m_objects [ idx ]; }
2020-07-14 11:52:34 +02:00
// PrintObject by its ObjectID, to be used to uniquely bind slicing warnings to their source PrintObjects
// in the notification center.
const PrintObject * get_object ( ObjectID object_id ) const {
auto it = std :: find_if ( m_objects . begin (), m_objects . end (),
2020-07-21 15:33:28 +02:00
[ object_id ]( const PrintObject * obj ) { return obj -> id () == object_id ; });
2020-07-14 11:52:34 +02:00
return ( it == m_objects . end ()) ? nullptr : * it ;
}
2021-02-03 15:12:53 +01:00
ConstPrintRegionPtrsAdaptor regions () const { return ConstPrintRegionPtrsAdaptor ( & m_regions ); }
2018-10-23 22:53:43 +02:00
// How many of PrintObject::copies() over all print objects are there?
// If zero, then the print is empty and the print shall not be executed.
unsigned int num_object_instances () const ;
2018-09-11 14:04:47 +02:00
2021-02-03 15:12:53 +01:00
// For Perl bindings.
PrintObjectPtrs & objects_mutable () { return m_objects ; }
PrintRegionPtrs & regions_mutable () { return m_regions ; }
2018-09-11 14:04:47 +02:00
const ExtrusionEntityCollection & skirt () const { return m_skirt ; }
const ExtrusionEntityCollection & brim () const { return m_brim ; }
2020-06-03 14:49:40 +02:00
// Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
// It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower.
// It does NOT encompass user extrusions generated by custom G-code,
// therefore it does NOT encompass the initial purge line.
// It does NOT encompass MMU/MMU2 starting (wipe) areas.
const Polygon & first_layer_convex_hull () const { return m_first_layer_convex_hull ; }
2018-09-11 14:04:47 +02:00
const PrintStatistics & print_statistics () const { return m_print_statistics ; }
2020-07-20 09:45:49 +02:00
PrintStatistics & print_statistics () { return m_print_statistics ; }
2017-05-25 22:27:53 +02:00
// Wipe tower support.
2018-09-11 14:04:47 +02:00
bool has_wipe_tower () const ;
2019-10-08 13:50:51 +02:00
const WipeTowerData & wipe_tower_data ( size_t extruders_cnt = 0 , double first_layer_height = 0. , double nozzle_diameter = 0. ) const ;
2020-01-15 16:20:16 +01:00
const ToolOrdering & tool_ordering () const { return m_tool_ordering ; }
2017-05-25 22:27:53 +02:00
2019-05-17 16:27:00 +02:00
std :: string output_filename ( const std :: string & filename_base = std :: string ()) const override ;
2017-09-01 17:30:18 +02:00
2018-09-11 14:04:47 +02:00
// Accessed by SupportMaterial
const PrintRegion * get_region ( size_t idx ) const { return m_regions [ idx ]; }
2020-01-15 15:35:56 +01:00
const ToolOrdering & get_tool_ordering () const { return m_wipe_tower_data . tool_ordering ; } // #ys_FIXME just for testing
2018-03-28 17:05:31 +02:00
protected :
2018-09-11 14:04:47 +02:00
// methods for handling regions
PrintRegion * get_region ( size_t idx ) { return m_regions [ idx ]; }
PrintRegion * add_region ();
PrintRegion * add_region ( const PrintRegionConfig & config );
2018-03-28 17:05:31 +02:00
2018-11-08 14:23:17 +01:00
// Invalidates the step, and its depending steps in Print.
bool invalidate_step ( PrintStep step );
2017-03-13 16:03:11 +01:00
private :
2019-07-25 14:39:19 +02:00
void config_diffs (
const DynamicPrintConfig & new_full_config ,
t_config_option_keys & print_diff , t_config_option_keys & object_diff , t_config_option_keys & region_diff ,
t_config_option_keys & full_config_diff ,
DynamicPrintConfig & filament_overrides ) const ;
2021-02-11 12:03:21 +01:00
bool invalidate_state_by_config_options ( const ConfigOptionResolver & new_config , const std :: vector < t_config_option_key > & opt_keys );
2017-09-01 17:30:18 +02:00
2018-09-11 14:04:47 +02:00
void _make_skirt ();
void _make_wipe_tower ();
2020-06-03 14:49:40 +02:00
void finalize_first_layer_convex_hull ();
// Islands of objects and their supports extruded at the 1st layer.
Polygons first_layer_islands () const ;
// Return 4 wipe tower corners in the world coordinates (shifted and rotated), including the wipe tower brim.
std :: vector < Point > first_layer_wipe_tower_corners () const ;
2018-03-23 11:41:20 +01:00
2018-11-02 20:41:49 +01:00
// Declared here to have access to Model / ModelObject / ModelInstance
static void model_volume_list_update_supports ( ModelObject & model_object_dst , const ModelObject & model_object_src );
2018-09-11 14:04:47 +02:00
PrintConfig m_config ;
PrintObjectConfig m_default_object_config ;
PrintRegionConfig m_default_region_config ;
PrintObjectPtrs m_objects ;
PrintRegionPtrs m_regions ;
// Ordered collections of extrusion paths to build skirt loops and brim.
ExtrusionEntityCollection m_skirt ;
ExtrusionEntityCollection m_brim ;
2020-06-03 14:49:40 +02:00
// Convex hull of the 1st layer extrusions.
// It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower.
// It does NOT encompass user extrusions generated by custom G-code,
// therefore it does NOT encompass the initial purge line.
// It does NOT encompass MMU/MMU2 starting (wipe) areas.
Polygon m_first_layer_convex_hull ;
Points m_skirt_convex_hull ;
2018-09-11 14:04:47 +02:00
// Following section will be consumed by the GCodeGenerator.
2020-01-15 16:20:16 +01:00
ToolOrdering m_tool_ordering ;
WipeTowerData m_wipe_tower_data { m_tool_ordering };
2018-09-11 14:04:47 +02:00
// Estimated print time, filament consumed.
PrintStatistics m_print_statistics ;
2018-03-28 17:05:31 +02:00
// To allow GCode to set the Print's GCodeExport step status.
friend class GCode ;
2018-09-11 14:04:47 +02:00
// Allow PrintObject to access m_mutex and m_cancel_callback.
friend class PrintObject ;
2014-05-06 11:07:18 +03:00
};
2018-11-08 14:23:17 +01:00
} /* slic3r_Print_hpp_ */
2013-12-20 01:36:42 +01:00
#endif