1 #ifndef slic3r_Print_hpp_
2 #define slic3r_Print_hpp_
3 
4 #include "PrintBase.hpp"
5 
6 #include "BoundingBox.hpp"
7 #include "ExtrusionEntityCollection.hpp"
8 #include "Flow.hpp"
9 #include "Point.hpp"
10 #include "Slicing.hpp"
11 #include "GCode/ToolOrdering.hpp"
12 #include "GCode/WipeTower.hpp"
13 #include "GCode/ThumbnailData.hpp"
14 #include "GCode/GCodeProcessor.hpp"
15 
16 #include "libslic3r.h"
17 
18 namespace Slic3r {
19 
20 class Print;
21 class PrintObject;
22 class ModelObject;
23 class GCode;
24 enum class SlicingMode : uint32_t;
25 class Layer;
26 class SupportLayer;
27 
28 namespace FillAdaptive {
29     struct Octree;
30     struct OctreeDeleter;
31     using OctreePtr = std::unique_ptr<Octree, OctreeDeleter>;
32 };
33 
34 // Print step IDs for keeping track of the print state.
35 // The Print steps are applied in this order.
36 enum PrintStep {
37     psWipeTower,
38     // Ordering of the tools on PrintObjects for a multi-material print.
39     // psToolOrdering is a synonym to psWipeTower, as the Wipe Tower calculates and modifies the ToolOrdering,
40     // while if printing without the Wipe Tower, the ToolOrdering is calculated as well.
41     psToolOrdering = psWipeTower,
42     psSkirt,
43     psBrim,
44     // Last step before G-code export, after this step is finished, the initial extrusion path preview
45     // should be refreshed.
46     psSlicingFinished = psBrim,
47     psGCodeExport,
48     psCount,
49 };
50 
51 enum PrintObjectStep {
52     posSlice, posPerimeters, posPrepareInfill,
53     posInfill, posIroning, posSupportMaterial, posCount,
54 };
55 
56 // A PrintRegion object represents a group of volumes to print
57 // sharing the same config (including the same assigned extruder(s))
58 class PrintRegion
59 {
60     friend class Print;
61 
62 // Methods NOT modifying the PrintRegion's state:
63 public:
print() const64     const Print*                print() const { return m_print; }
config() const65     const PrintRegionConfig&    config() const { return m_config; }
66 	// 1-based extruder identifier for this region and role.
67 	unsigned int 				extruder(FlowRole role) const;
68     Flow                        flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject &object) const;
69     // Average diameter of nozzles participating on extruding this region.
70     coordf_t                    nozzle_dmr_avg(const PrintConfig &print_config) const;
71     // Average diameter of nozzles participating on extruding this region.
72     coordf_t                    bridging_height_avg(const PrintConfig &print_config) const;
73 
74     // Collect 0-based extruder indices used to print this region's object.
75 	void                        collect_object_printing_extruders(std::vector<unsigned int> &object_extruders) const;
76 	static void                 collect_object_printing_extruders(const PrintConfig &print_config, const PrintRegionConfig &region_config, std::vector<unsigned int> &object_extruders);
77 
78 // Methods modifying the PrintRegion's state:
79 public:
print()80     Print*                      print() { return m_print; }
set_config(const PrintRegionConfig & config)81     void                        set_config(const PrintRegionConfig &config) { m_config = config; }
set_config(PrintRegionConfig && config)82     void                        set_config(PrintRegionConfig &&config) { m_config = std::move(config); }
config_apply_only(const ConfigBase & other,const t_config_option_keys & keys,bool ignore_nonexistent=false)83     void                        config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false)
84                                         { this->m_config.apply_only(other, keys, ignore_nonexistent); }
85 
86 protected:
87     size_t             m_refcnt;
88 
89 private:
90     Print             *m_print;
91     PrintRegionConfig  m_config;
92 
PrintRegion(Print * print)93     PrintRegion(Print* print) : m_refcnt(0), m_print(print) {}
PrintRegion(Print * print,const PrintRegionConfig & config)94     PrintRegion(Print* print, const PrintRegionConfig &config) : m_refcnt(0), m_print(print), m_config(config) {}
95     ~PrintRegion() = default;
96 };
97 
98 
99 typedef std::vector<Layer*> LayerPtrs;
100 typedef std::vector<SupportLayer*> SupportLayerPtrs;
101 class BoundingBoxf3;        // TODO: for temporary constructor parameter
102 
103 // Single instance of a PrintObject.
104 // As multiple PrintObjects may be generated for a single ModelObject (their instances differ in rotation around Z),
105 // ModelObject's instancess will be distributed among these multiple PrintObjects.
106 struct PrintInstance
107 {
108     // Parent PrintObject
109     PrintObject 		*print_object;
110     // Source ModelInstance of a ModelObject, for which this print_object was created.
111 	const ModelInstance *model_instance;
112 	// Shift of this instance's center into the world coordinates.
113 	Point 				 shift;
114 };
115 
116 typedef std::vector<PrintInstance> PrintInstances;
117 
118 class PrintObject : public PrintObjectBaseWithState<Print, PrintObjectStep, posCount>
119 {
120 private: // Prevents erroneous use by other classes.
121     typedef PrintObjectBaseWithState<Print, PrintObjectStep, posCount> Inherited;
122 
123 public:
124     // vector of (layer height ranges and vectors of volume ids), indexed by region_id
125     std::vector<std::vector<std::pair<t_layer_height_range, int>>> region_volumes;
126 
127     // Size of an object: XYZ in scaled coordinates. The size might not be quite snug in XY plane.
size() const128     const Vec3crd&          size() const			{ return m_size; }
config() const129     const PrintObjectConfig& config() const         { return m_config; }
layers() const130     const LayerPtrs&        layers() const          { return m_layers; }
support_layers() const131     const SupportLayerPtrs& support_layers() const  { return m_support_layers; }
trafo() const132     const Transform3d&      trafo() const           { return m_trafo; }
instances() const133     const PrintInstances&   instances() const       { return m_instances; }
134 
135     // Bounding box is used to align the object infill patterns, and to calculate attractor for the rear seam.
136     // The bounding box may not be quite snug.
bounding_box() const137     BoundingBox             bounding_box()    const { return BoundingBox(Point(- m_size.x() / 2, - m_size.y() / 2), Point(m_size.x() / 2, m_size.y() / 2)); }
138     // Height is used for slicing, for sorting the objects by height for sequential printing and for checking vertical clearence in sequential print mode.
139     // The height is snug.
height() const140     coord_t 				height() 		  const { return m_size.z(); }
141     // Centering offset of the sliced mesh from the scaled and rotated mesh of the model.
center_offset() const142     const Point& 			center_offset()   const { return m_center_offset; }
143 
144     // adds region_id, too, if necessary
add_region_volume(unsigned int region_id,int volume_id,const t_layer_height_range & layer_range)145     void add_region_volume(unsigned int region_id, int volume_id, const t_layer_height_range &layer_range) {
146         if (region_id >= region_volumes.size())
147 			region_volumes.resize(region_id + 1);
148         region_volumes[region_id].emplace_back(layer_range, volume_id);
149     }
150     // This is the *total* layer count (including support layers)
151     // this value is not supposed to be compared with Layer::id
152     // since they have different semantics.
total_layer_count() const153     size_t 			total_layer_count() const { return this->layer_count() + this->support_layer_count(); }
layer_count() const154     size_t 			layer_count() const { return m_layers.size(); }
155     void 			clear_layers();
get_layer(int idx) const156     const Layer* 	get_layer(int idx) const { return m_layers[idx]; }
get_layer(int idx)157     Layer* 			get_layer(int idx) 		 { return m_layers[idx]; }
158     // Get a layer exactly at print_z.
159     const Layer*	get_layer_at_printz(coordf_t print_z) const;
160     Layer*			get_layer_at_printz(coordf_t print_z);
161     // Get a layer approximately at print_z.
162     const Layer*	get_layer_at_printz(coordf_t print_z, coordf_t epsilon) const;
163     Layer*			get_layer_at_printz(coordf_t print_z, coordf_t epsilon);
164     // Get the first layer approximately bellow print_z.
165     const Layer*	get_first_layer_bellow_printz(coordf_t print_z, coordf_t epsilon) const;
166 
167     // print_z: top of the layer; slice_z: center of the layer.
168     Layer* add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
169 
support_layer_count() const170     size_t support_layer_count() const { return m_support_layers.size(); }
171     void clear_support_layers();
get_support_layer(int idx)172     SupportLayer* get_support_layer(int idx) { return m_support_layers[idx]; }
173     SupportLayer* add_support_layer(int id, coordf_t height, coordf_t print_z);
174     SupportLayerPtrs::const_iterator insert_support_layer(SupportLayerPtrs::const_iterator pos, size_t id, coordf_t height, coordf_t print_z, coordf_t slice_z);
175     void delete_support_layer(int idx);
176 
177     // Initialize the layer_height_profile from the model_object's layer_height_profile, from model_object's layer height table, or from slicing parameters.
178     // Returns true, if the layer_height_profile was changed.
179     static bool update_layer_height_profile(const ModelObject &model_object, const SlicingParameters &slicing_parameters, std::vector<coordf_t> &layer_height_profile);
180 
181     // Collect the slicing parameters, to be used by variable layer thickness algorithm,
182     // by the interactive layer height editor and by the printing process itself.
183     // The slicing parameters are dependent on various configuration values
184     // (layer height, first layer height, raft settings, print nozzle diameter etc).
slicing_parameters() const185     const SlicingParameters&    slicing_parameters() const { return m_slicing_params; }
186     static SlicingParameters    slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z);
187 
188     // returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
189     std::vector<unsigned int>   object_extruders() const;
190 
191     // Called by make_perimeters()
192     void slice();
193 
194     // Helpers to slice support enforcer / blocker meshes by the support generator.
195     std::vector<ExPolygons>     slice_support_volumes(const ModelVolumeType &model_volume_type) const;
slice_support_blockers() const196     std::vector<ExPolygons>     slice_support_blockers() const { return this->slice_support_volumes(ModelVolumeType::SUPPORT_BLOCKER); }
slice_support_enforcers() const197     std::vector<ExPolygons>     slice_support_enforcers() const { return this->slice_support_volumes(ModelVolumeType::SUPPORT_ENFORCER); }
198 
199     // Helpers to project custom facets on slices
200     void project_and_append_custom_facets(bool seam, EnforcerBlockerType type, std::vector<ExPolygons>& expolys) const;
201 
202 private:
203     // to be called from Print only.
204     friend class Print;
205 
206 	PrintObject(Print* print, ModelObject* model_object, const Transform3d& trafo, PrintInstances&& instances);
207 	~PrintObject() = default;
208 
config_apply(const ConfigBase & other,bool ignore_nonexistent=false)209     void                    config_apply(const ConfigBase &other, bool ignore_nonexistent = false) { this->m_config.apply(other, ignore_nonexistent); }
config_apply_only(const ConfigBase & other,const t_config_option_keys & keys,bool ignore_nonexistent=false)210     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); }
211     PrintBase::ApplyStatus  set_instances(PrintInstances &&instances);
212     // Invalidates the step, and its depending steps in PrintObject and Print.
213     bool                    invalidate_step(PrintObjectStep step);
214     // Invalidates all PrintObject and Print steps.
215     bool                    invalidate_all_steps();
216     // Invalidate steps based on a set of parameters changed.
217     bool                    invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
218     // If ! m_slicing_params.valid, recalculate.
219     void                    update_slicing_parameters();
220 
221     static PrintObjectConfig object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders);
222     static PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders);
223 
224 private:
225     void make_perimeters();
226     void prepare_infill();
227     void infill();
228     void ironing();
229     void generate_support_material();
230 
231     void _slice(const std::vector<coordf_t> &layer_height_profile);
232     std::string _fix_slicing_errors();
233     void simplify_slices(double distance);
234     bool has_support_material() const;
235     void detect_surfaces_type();
236     void process_external_surfaces();
237     void discover_vertical_shells();
238     void bridge_over_infill();
239     void clip_fill_surfaces();
240     void discover_horizontal_shells();
241     void combine_infill();
242     void _generate_support_material();
243     std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> prepare_adaptive_infill_data();
244 
245     // XYZ in scaled coordinates
246     Vec3crd									m_size;
247     PrintObjectConfig                       m_config;
248     // Translation in Z + Rotation + Scaling / Mirroring.
249     Transform3d                             m_trafo = Transform3d::Identity();
250     // Slic3r::Point objects in scaled G-code coordinates
251     std::vector<PrintInstance>              m_instances;
252     // The mesh is being centered before thrown to Clipper, so that the Clipper's fixed coordinates require less bits.
253     // This is the adjustment of the  the Object's coordinate system towards PrintObject's coordinate system.
254     Point                                   m_center_offset;
255 
256     SlicingParameters                       m_slicing_params;
257     LayerPtrs                               m_layers;
258     SupportLayerPtrs                        m_support_layers;
259 
260     // this is set to true when LayerRegion->slices is split in top/internal/bottom
261     // so that next call to make_perimeters() performs a union() before computing loops
262     bool                    				m_typed_slices = false;
263 
264     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;
slice_region(size_t region_id,const std::vector<float> & z,SlicingMode mode) const265     std::vector<ExPolygons> slice_region(size_t region_id, const std::vector<float> &z, SlicingMode mode) const
266         { return this->slice_region(region_id, z, mode, 0, mode); }
267     std::vector<ExPolygons> slice_modifiers(size_t region_id, const std::vector<float> &z) const;
268     std::vector<ExPolygons> slice_volumes(
269         const std::vector<float> &z,
270         SlicingMode mode, size_t slicing_mode_normal_below_layer, SlicingMode mode_below,
271         const std::vector<const ModelVolume*> &volumes) const;
slice_volumes(const std::vector<float> & z,SlicingMode mode,const std::vector<const ModelVolume * > & volumes) const272     std::vector<ExPolygons> slice_volumes(const std::vector<float> &z, SlicingMode mode, const std::vector<const ModelVolume*> &volumes) const
273         { return this->slice_volumes(z, mode, 0, mode, volumes); }
274     std::vector<ExPolygons> slice_volume(const std::vector<float> &z, SlicingMode mode, const ModelVolume &volume) const;
275     std::vector<ExPolygons> slice_volume(const std::vector<float> &z, const std::vector<t_layer_height_range> &ranges, SlicingMode mode, const ModelVolume &volume) const;
276 };
277 
278 struct WipeTowerData
279 {
280     // Following section will be consumed by the GCodeGenerator.
281     // Tool ordering of a non-sequential print has to be known to calculate the wipe tower.
282     // Cache it here, so it does not need to be recalculated during the G-code generation.
283     ToolOrdering                                         &tool_ordering;
284     // Cache of tool changes per print layer.
285     std::unique_ptr<std::vector<WipeTower::ToolChangeResult>> priming;
286     std::vector<std::vector<WipeTower::ToolChangeResult>> tool_changes;
287     std::unique_ptr<WipeTower::ToolChangeResult>          final_purge;
288     std::vector<float>                                    used_filament;
289     int                                                   number_of_toolchanges;
290 
291     // Depth of the wipe tower to pass to GLCanvas3D for exact bounding box:
292     float                                                 depth;
293     float                                                 brim_width;
294 
clearSlic3r::WipeTowerData295     void clear() {
296         priming.reset(nullptr);
297         tool_changes.clear();
298         final_purge.reset(nullptr);
299         used_filament.clear();
300         number_of_toolchanges = -1;
301         depth = 0.f;
302         brim_width = 0.f;
303     }
304 
305 private:
306 	// Only allow the WipeTowerData to be instantiated internally by Print,
307 	// as this WipeTowerData shares reference to Print::m_tool_ordering.
308 	friend class Print;
WipeTowerDataSlic3r::WipeTowerData309 	WipeTowerData(ToolOrdering &tool_ordering) : tool_ordering(tool_ordering) { clear(); }
310 	WipeTowerData(const WipeTowerData & /* rhs */) = delete;
311 	WipeTowerData &operator=(const WipeTowerData & /* rhs */) = delete;
312 };
313 
314 struct PrintStatistics
315 {
PrintStatisticsSlic3r::PrintStatistics316     PrintStatistics() { clear(); }
317     std::string                     estimated_normal_print_time;
318     std::string                     estimated_silent_print_time;
319     double                          total_used_filament;
320     double                          total_extruded_volume;
321     double                          total_cost;
322     int                             total_toolchanges;
323     double                          total_weight;
324     double                          total_wipe_tower_cost;
325     double                          total_wipe_tower_filament;
326     std::map<size_t, float>         filament_stats;
327 
328     // Config with the filled in print statistics.
329     DynamicConfig           config() const;
330     // Config with the statistics keys populated with placeholder strings.
331     static DynamicConfig    placeholders();
332     // Replace the print statistics placeholders in the path.
333     std::string             finalize_output_path(const std::string &path_in) const;
334 
clearSlic3r::PrintStatistics335     void clear() {
336         total_used_filament    = 0.;
337         total_extruded_volume  = 0.;
338         total_cost             = 0.;
339         total_toolchanges      = 0;
340         total_weight           = 0.;
341         total_wipe_tower_cost  = 0.;
342         total_wipe_tower_filament = 0.;
343         filament_stats.clear();
344     }
345 };
346 
347 typedef std::vector<PrintObject*> PrintObjectPtrs;
348 typedef std::vector<PrintRegion*> PrintRegionPtrs;
349 
350 // The complete print tray with possibly multiple objects.
351 class Print : public PrintBaseWithState<PrintStep, psCount>
352 {
353 private: // Prevents erroneous use by other classes.
354     typedef PrintBaseWithState<PrintStep, psCount> Inherited;
355 
356 public:
357     Print() = default;
~Print()358 	virtual ~Print() { this->clear(); }
359 
technology() const360 	PrinterTechnology	technology() const noexcept override { return ptFFF; }
361 
362     // Methods, which change the state of Print / PrintObject / PrintRegion.
363     // The following methods are synchronized with process() and export_gcode(),
364     // so that process() and export_gcode() may be called from a background thread.
365     // In case the following methods need to modify data processed by process() or export_gcode(),
366     // a cancellation callback is executed to stop the background processing before the operation.
367     void                clear() override;
empty() const368     bool                empty() const override { return m_objects.empty(); }
369     // List of existing PrintObject IDs, to remove notifications for non-existent IDs.
370     std::vector<ObjectID> print_object_ids() const override;
371 
372     ApplyStatus         apply(const Model &model, DynamicPrintConfig config) override;
373 
374     void                process() override;
375     // Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
376     // If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
377     std::string         export_gcode(const std::string& path_template, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
378 
379     // methods for handling state
is_step_done(PrintStep step) const380     bool                is_step_done(PrintStep step) const { return Inherited::is_step_done(step); }
381     // Returns true if an object step is done on all objects and there's at least one object.
382     bool                is_step_done(PrintObjectStep step) const;
383     // Returns true if the last step was finished with success.
finished() const384     bool                finished() const override { return this->is_step_done(psGCodeExport); }
385 
386     bool                has_infinite_skirt() const;
387     bool                has_skirt() const;
388 
389     // Returns an empty string if valid, otherwise returns an error message.
390     std::string         validate() const override;
391     double              skirt_first_layer_height() const;
392     Flow                brim_flow() const;
393     Flow                skirt_flow() const;
394 
395     std::vector<unsigned int> object_extruders() const;
396     std::vector<unsigned int> support_material_extruders() const;
397     std::vector<unsigned int> extruders() const;
398     double              max_allowed_layer_height() const;
399     bool                has_support_material() const;
400     // Make sure the background processing has no access to this model_object during this call!
401     void                auto_assign_extruders(ModelObject* model_object) const;
402 
config() const403     const PrintConfig&          config() const { return m_config; }
default_object_config() const404     const PrintObjectConfig&    default_object_config() const { return m_default_object_config; }
default_region_config() const405     const PrintRegionConfig&    default_region_config() const { return m_default_region_config; }
406     //FIXME returning const vector to non-const PrintObject*, caller could modify PrintObjects!
objects() const407     const PrintObjectPtrs&      objects() const { return m_objects; }
get_object(size_t idx)408     PrintObject*                get_object(size_t idx) { return m_objects[idx]; }
get_object(size_t idx) const409     const PrintObject*          get_object(size_t idx) const { return m_objects[idx]; }
410     // PrintObject by its ObjectID, to be used to uniquely bind slicing warnings to their source PrintObjects
411     // in the notification center.
get_object(ObjectID object_id) const412     const PrintObject*          get_object(ObjectID object_id) const {
413         auto it = std::find_if(m_objects.begin(), m_objects.end(),
414             [object_id](const PrintObject *obj) { return obj->id() == object_id; });
415         return (it == m_objects.end()) ? nullptr : *it;
416     }
regions() const417     const PrintRegionPtrs&      regions() const { return m_regions; }
418     // How many of PrintObject::copies() over all print objects are there?
419     // If zero, then the print is empty and the print shall not be executed.
420     unsigned int                num_object_instances() const;
421 
skirt() const422     const ExtrusionEntityCollection& skirt() const { return m_skirt; }
brim() const423     const ExtrusionEntityCollection& brim() const { return m_brim; }
424     // Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
425     // It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower.
426     // It does NOT encompass user extrusions generated by custom G-code,
427     // therefore it does NOT encompass the initial purge line.
428     // It does NOT encompass MMU/MMU2 starting (wipe) areas.
first_layer_convex_hull() const429     const Polygon&                   first_layer_convex_hull() const { return m_first_layer_convex_hull; }
430 
print_statistics() const431     const PrintStatistics&      print_statistics() const { return m_print_statistics; }
print_statistics()432     PrintStatistics&            print_statistics() { return m_print_statistics; }
433 
434     // Wipe tower support.
435     bool                        has_wipe_tower() const;
436     const WipeTowerData&        wipe_tower_data(size_t extruders_cnt = 0, double first_layer_height = 0., double nozzle_diameter = 0.) const;
tool_ordering() const437     const ToolOrdering& 		tool_ordering() const { return m_tool_ordering; }
438 
439 	std::string                 output_filename(const std::string &filename_base = std::string()) const override;
440 
441     // Accessed by SupportMaterial
get_region(size_t idx) const442     const PrintRegion*  get_region(size_t idx) const  { return m_regions[idx]; }
get_tool_ordering() const443     const ToolOrdering& get_tool_ordering() const { return m_wipe_tower_data.tool_ordering; }   // #ys_FIXME just for testing
444 
445 protected:
446     // methods for handling regions
get_region(size_t idx)447     PrintRegion*        get_region(size_t idx)        { return m_regions[idx]; }
448     PrintRegion*        add_region();
449     PrintRegion*        add_region(const PrintRegionConfig &config);
450 
451     // Invalidates the step, and its depending steps in Print.
452     bool                invalidate_step(PrintStep step);
453 
454 private:
455 	void 				config_diffs(
456 		const DynamicPrintConfig &new_full_config,
457 		t_config_option_keys &print_diff, t_config_option_keys &object_diff, t_config_option_keys &region_diff,
458 		t_config_option_keys &full_config_diff,
459 		DynamicPrintConfig &filament_overrides) const;
460 
461     bool                invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
462 
463     void                _make_skirt();
464     void                _make_brim();
465     void                _make_wipe_tower();
466     void                finalize_first_layer_convex_hull();
467 
468     // Islands of objects and their supports extruded at the 1st layer.
469     Polygons            first_layer_islands() const;
470     // Return 4 wipe tower corners in the world coordinates (shifted and rotated), including the wipe tower brim.
471     std::vector<Point>  first_layer_wipe_tower_corners() const;
472 
473     // Declared here to have access to Model / ModelObject / ModelInstance
474     static void         model_volume_list_update_supports(ModelObject &model_object_dst, const ModelObject &model_object_src);
475 
476     PrintConfig                             m_config;
477     PrintObjectConfig                       m_default_object_config;
478     PrintRegionConfig                       m_default_region_config;
479     PrintObjectPtrs                         m_objects;
480     PrintRegionPtrs                         m_regions;
481 
482     // Ordered collections of extrusion paths to build skirt loops and brim.
483     ExtrusionEntityCollection               m_skirt;
484     ExtrusionEntityCollection               m_brim;
485     // Convex hull of the 1st layer extrusions.
486     // It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower.
487     // It does NOT encompass user extrusions generated by custom G-code,
488     // therefore it does NOT encompass the initial purge line.
489     // It does NOT encompass MMU/MMU2 starting (wipe) areas.
490     Polygon                                 m_first_layer_convex_hull;
491     Points                                  m_skirt_convex_hull;
492 
493     // Following section will be consumed by the GCodeGenerator.
494     ToolOrdering 							m_tool_ordering;
495     WipeTowerData                           m_wipe_tower_data {m_tool_ordering};
496 
497     // Estimated print time, filament consumed.
498     PrintStatistics                         m_print_statistics;
499 
500     // To allow GCode to set the Print's GCodeExport step status.
501     friend class GCode;
502     // Allow PrintObject to access m_mutex and m_cancel_callback.
503     friend class PrintObject;
504 };
505 
506 } /* slic3r_Print_hpp_ */
507 
508 #endif
509