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 ®ion_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 ®ion_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