1 //Copyright (c) 2018 Ultimaker B.V. 2 //CuraEngine is released under the terms of the AGPLv3 or higher. 3 4 #ifndef GCODE_WRITER_H 5 #define GCODE_WRITER_H 6 7 #include <fstream> 8 #include "FanSpeedLayerTime.h" 9 #include "gcodeExport.h" 10 #include "LayerPlanBuffer.h" 11 #include "settings/PathConfigStorage.h" //For the MeshPathConfigs subclass. 12 #include "utils/NoCopy.h" 13 14 namespace std 15 { 16 template<typename T> class optional; 17 } 18 19 namespace cura 20 { 21 22 class AngleDegrees; 23 class Polygons; 24 class SkinPart; 25 class SliceDataStorage; 26 class SliceMeshStorage; 27 class SliceLayer; 28 class SliceLayerPart; 29 class TimeKeeper; 30 31 /*! 32 * Secondary stage in Fused Filament Fabrication processing: The generated polygons are used in the gcode generation. 33 * Some polygons in the SliceDataStorage signify areas which are to be filled with parallel lines, 34 * while other polygons signify the contours which should be printed. 35 * 36 * The main function of this class is FffGcodeWriter::writeGCode(). 37 */ 38 class FffGcodeWriter : public NoCopy 39 { 40 friend class Scene; // cause WireFrame2Gcode uses the member [gcode] (TODO) 41 friend class FffProcessor; //Because FffProcessor exposes finalize (TODO) 42 private: 43 coord_t max_object_height; //!< The maximal height of all previously sliced meshgroups, used to avoid collision when moving to the next meshgroup to print. 44 45 /* 46 * Buffer for all layer plans (of type LayerPlan) 47 * 48 * The layer plans are buffered so that we can start heating up a nozzle several layers before it needs to be used. 49 * Another reason is to perform Auto Temperature. 50 */ 51 LayerPlanBuffer layer_plan_buffer; 52 53 /*! 54 * The class holding the current state of the gcode being written. 55 * 56 * It holds information such as the last written position etc. 57 */ 58 GCodeExport gcode; 59 60 /*! 61 * The gcode file to write to when using CuraEngine as command line tool. 62 */ 63 std::ofstream output_file; 64 65 /*! 66 * For each raft/filler layer, the extruders to be used in that layer in the order in which they are going to be used. 67 * The first number is the first raft layer. Indexing is shifted compared to normal negative layer numbers for raft/filler layers. 68 */ 69 std::vector<std::vector<size_t>> extruder_order_per_layer_negative_layers; 70 71 std::vector<std::vector<size_t>> extruder_order_per_layer; //!< For each layer, the extruders to be used in that layer in the order in which they are going to be used 72 73 std::vector<std::vector<size_t>> mesh_order_per_extruder; //!< For each extruder, the order of the meshes (first element is first mesh to be printed) 74 75 /*! 76 * For each extruder on which layer the prime will be planned, 77 * or a large negative number if it's already planned outside of \ref FffGcodeWriter::processLayer 78 * 79 * Depending on whether we need to prime on the first layer, or anywhere in the print, 80 * the layer numbers are all zero (or less in case of raft) 81 * or they are the first layer at which the extruder is needed 82 */ 83 LayerIndex extruder_prime_layer_nr[MAX_EXTRUDERS]; 84 85 std::vector<FanSpeedLayerTimeSettings> fan_speed_layer_time_settings_per_extruder; //!< The settings used relating to minimal layer time and fan speeds. Configured for each extruder. 86 87 public: 88 /* 89 * \brief Construct a g-code writer. 90 * 91 * This sets the initial state of the printer correctly in itself, so that 92 * it's ready for writing. 93 */ 94 FffGcodeWriter(); 95 96 /*! 97 * Set the target to write gcode to: to a file. 98 * 99 * Used when CuraEngine is used as command line tool. 100 * 101 * \param filename The filename of the file to which to write the gcode. 102 */ setTargetFile(const char * filename)103 bool setTargetFile(const char* filename) 104 { 105 output_file.open(filename); 106 if (output_file.is_open()) 107 { 108 gcode.setOutputStream(&output_file); 109 return true; 110 } 111 return false; 112 } 113 114 /*! 115 * Set the target to write gcode to: an output stream. 116 * 117 * Used when CuraEngine is NOT used as command line tool. 118 * 119 * \param stream The stream to write gcode to. 120 */ setTargetStream(std::ostream * stream)121 void setTargetStream(std::ostream* stream) 122 { 123 gcode.setOutputStream(stream); 124 } 125 126 /*! 127 * Get the total extruded volume for a specific extruder in mm^3 128 * 129 * Retractions and unretractions don't contribute to this. 130 * 131 * \param extruder_nr The extruder number for which to get the total netto extruded volume 132 * \return total filament printed in mm^3 133 */ getTotalFilamentUsed(int extruder_nr)134 double getTotalFilamentUsed(int extruder_nr) 135 { 136 return gcode.getTotalFilamentUsed(extruder_nr); 137 } 138 139 /*! 140 * Get the total estimated print time in seconds for each feature 141 * 142 * \return total print time in seconds for each feature 143 */ getTotalPrintTimePerFeature()144 std::vector<Duration> getTotalPrintTimePerFeature() 145 { 146 return gcode.getTotalPrintTimePerFeature(); 147 } 148 149 /*! 150 * Write all the gcode for the current meshgroup. 151 * This is the primary function of this class. 152 * 153 * \param[in] storage The data storage from which to get the polygons to print and the areas to fill. 154 * \param timeKeeper The stop watch to see how long it takes for each of the stages in the slicing process. 155 */ 156 void writeGCode(SliceDataStorage& storage, TimeKeeper& timeKeeper); 157 158 private: 159 /*! 160 * \brief Set the FffGcodeWriter::fan_speed_layer_time_settings by 161 * retrieving all settings from the global/per-meshgroup settings. 162 */ 163 void setConfigFanSpeedLayerTime(); 164 165 /*! 166 * Create and set the SliceDataStorage::coasting_config for each extruder. 167 * 168 * \param[out] storage The data storage to which to save the configuration 169 */ 170 void setConfigCoasting(SliceDataStorage& storage); 171 172 /*! 173 * Set the retraction config globally, per extruder and per mesh. 174 * 175 * \param[out] storage The data storage to which to save the configurations 176 */ 177 void setConfigRetraction(SliceDataStorage& storage); 178 179 /*! 180 * Set the wipe config globally, per extruder. 181 * 182 * \param[out] storage The data storage to which to save the configurations 183 */ 184 void setConfigWipe(SliceDataStorage& storage); 185 186 /*! 187 * Get the extruder with which to start the print. 188 * 189 * Generally this is the adhesion_extruder_nr, but in case the platform adhesion type is none, 190 * the extruder with lowest number which is used on the first layer is used as initial extruder. 191 * 192 * \param[in] storage where to get settings from. 193 */ 194 unsigned int getStartExtruder(const SliceDataStorage& storage); 195 196 /*! 197 * Set the infill angles and skin angles in the SliceDataStorage. 198 * 199 * These lists of angles are cycled through to get the infill angle of a specific layer. 200 * 201 * \param mesh The mesh for which to determine the infill and skin angles. 202 */ 203 void setInfillAndSkinAngles(SliceMeshStorage& mesh); 204 205 /*! 206 * Set the support and interface infill angles in the SliceDataStorage. 207 * 208 * Default angles depend on which pattern it's using and in certain patterns it 209 * alternates between layers. 210 * 211 * These lists of angles are cycled through to get the support infill angle of a specific layer. 212 * 213 * \param storage The storage for which to determine the support infill angles. 214 */ 215 void setSupportAngles(SliceDataStorage& storage); 216 217 /*! 218 * Set temperatures for the initial layer. Called by 'processStartingCode' and whenever a new object is started at layer 0. 219 * 220 * \param[in] storage where the slice data is stored. 221 * \param[in] start_extruder_nr The extruder with which to start the print. 222 */ 223 void processInitialLayerTemperature(const SliceDataStorage& storage, const size_t start_extruder_nr); 224 225 /*! 226 * Set temperatures and perform initial priming. 227 * 228 * Write a stub header if CuraEngine is in command line tool mode. (Cause writing the header afterwards would entail moving all gcode down.) 229 * 230 * \param[in] storage where the slice data is stored. 231 * \param[in] start_extruder_nr The extruder with which to start the print. 232 */ 233 void processStartingCode(const SliceDataStorage& storage, const size_t start_extruder_nr); 234 235 /*! 236 * Move up and over the already printed meshgroups to print the next meshgroup. 237 * 238 * \param[in] storage where the slice data is stored. 239 */ 240 void processNextMeshGroupCode(const SliceDataStorage& storage); 241 242 /*! 243 * Add raft layer plans onto the FffGcodeWriter::layer_plan_buffer 244 * 245 * \param[in,out] storage where the slice data is stored. 246 */ 247 void processRaft(const SliceDataStorage& storage); 248 249 /*! 250 * Convert the polygon data of a layer into a layer plan on the FffGcodeWriter::layer_plan_buffer 251 * 252 * In case of negative layer numbers, create layers only containing the data from 253 * the helper parts (support etc) to fill up the gap between the raft and the model. 254 * 255 * \param[in] storage where the slice data is stored. 256 * \param layer_nr The index of the layer to write the gcode of. 257 * \param total_layers The total number of layers. 258 * \return The layer plans 259 */ 260 LayerPlan& processLayer(const SliceDataStorage& storage, LayerIndex layer_nr, const size_t total_layers) const; 261 262 /*! 263 * This function checks whether prime blob should happen for any extruder on the first layer. 264 * Priming will always happen, but the actual priming may or may not include a prime blob. 265 * 266 * Technically, this function checks whether any extruder needs to be primed (with a prime blob) 267 * separately just before they are used. 268 * 269 * \return whether any extruder need to be primed separately just before they are used 270 */ 271 bool getExtruderNeedPrimeBlobDuringFirstLayer(const SliceDataStorage& storage, const size_t extruder_nr) const; 272 273 /*! 274 * Plan priming of all used extruders which haven't been primed yet 275 * \param[in] storage where the slice data is stored. 276 * \param layer_plan The initial planning of the g-code of the layer. 277 */ 278 void ensureAllExtrudersArePrimed(const SliceDataStorage& storage, LayerPlan& layer_plan) const; 279 280 /*! 281 * Add the skirt or the brim to the layer plan \p gcodeLayer if it hasn't already been added yet. 282 * 283 * This function should be called for only one layer; 284 * calling it for multiple layers results in the skirt/brim being printed on multiple layers. 285 * 286 * \param storage where the slice data is stored. 287 * \param gcodeLayer The initial planning of the g-code of the layer. 288 * \param extruder_nr The extruder train for which to process the skirt or 289 * brim. 290 */ 291 void processSkirtBrim(const SliceDataStorage& storage, LayerPlan& gcodeLayer, unsigned int extruder_nr) const; 292 293 /*! 294 * Adds the ooze shield to the layer plan \p gcodeLayer. 295 * 296 * \param[in] storage where the slice data is stored. 297 * \param gcodeLayer The initial planning of the gcode of the layer. 298 */ 299 void processOozeShield(const SliceDataStorage& storage, LayerPlan& gcodeLayer) const; 300 301 /*! 302 * Adds the draft protection screen to the layer plan \p gcodeLayer. 303 * 304 * \param[in] storage where the slice data is stored. 305 * \param gcodeLayer The initial planning of the gcode of the layer. 306 */ 307 void processDraftShield(const SliceDataStorage& storage, LayerPlan& gcodeLayer) const; 308 309 /*! 310 * Calculate in which order to plan the extruders for each layer 311 * Store the order of extruders for each layer in extruder_order_per_layer for normal layers 312 * and the order of extruders for raft/filler layers in extruder_order_per_layer_negative_layers. 313 * 314 * Only extruders which are (most probably) going to be used are planned 315 * 316 * \note At the planning stage we only have information on areas, not how those are filled. 317 * If an area is too small to be filled with anything it will still get specified as being used with the extruder for that area. 318 * 319 * Computes \ref FffGcodeWriter::extruder_prime_layer_nr, \ref FffGcodeWriter::extruder_order_per_layer and \ref FffGcodeWriter::extruder_order_per_layer_negative_layers 320 * 321 * \param[in] storage where the slice data is stored. 322 */ 323 void calculateExtruderOrderPerLayer(const SliceDataStorage& storage); 324 325 /*! 326 * Gets a list of extruders that are used on the given layer, but excluding the given starting extruder. 327 * When it's on the first layer, the prime blob will also be taken into account. 328 * 329 * \note At the planning stage we only have information on areas, not how those are filled. 330 * If an area is too small to be filled with anything it will still get specified as being used with the extruder for that area. 331 * 332 * \param[in] storage where the slice data is stored. 333 * \param current_extruder The current extruder with which we last printed 334 * \return The order of extruders for a layer beginning with \p current_extruder 335 */ 336 std::vector<size_t> getUsedExtrudersOnLayerExcludingStartingExtruder(const SliceDataStorage& storage, const size_t start_extruder, const LayerIndex& layer_nr) const; 337 338 /*! 339 * Calculate in which order to plan the meshes of a specific extruder 340 * Each mesh which has some feature printed with the extruder is included in this order. 341 * One mesh can occur in the mesh order of multiple extruders. 342 * 343 * \param[in] storage where the slice data is stored. 344 * \param extruder_nr The extruder for which to determine the order 345 * \return A vector of mesh indices ordered on print order for that extruder. 346 */ 347 std::vector<size_t> calculateMeshOrder(const SliceDataStorage& storage, const size_t extruder_nr) const; 348 349 /*! 350 * Add a single layer from a single mesh-volume to the layer plan \p gcodeLayer in mesh surface mode. 351 * 352 * \param[in] storage where the slice data is stored. 353 * \param mesh The mesh to add to the layer plan \p gcodeLayer. 354 * \param mesh_config the line config with which to print a print feature 355 * \param gcodeLayer The initial planning of the gcode of the layer. 356 */ 357 void addMeshLayerToGCode_meshSurfaceMode(const SliceDataStorage& storage, const SliceMeshStorage& mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, LayerPlan& gcodeLayer) const; 358 359 /*! 360 * Add the open polylines from a single layer from a single mesh-volume to the layer plan \p gcodeLayer for mesh the surface modes. 361 * 362 * \param[in] storage where the slice data is stored. 363 * \param mesh The mesh for which to add to the layer plan \p gcodeLayer. 364 * \param mesh_config the line config with which to print a print feature 365 * \param gcodeLayer The initial planning of the gcode of the layer. 366 */ 367 void addMeshOpenPolyLinesToGCode(const SliceMeshStorage& mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, LayerPlan& gcode_layer) const; 368 369 /*! 370 * Add all features of a given extruder from a single layer from a single mesh-volume to the layer plan \p gcode_layer. 371 * 372 * This adds all features (e.g. walls, skin etc.) of this \p mesh to the gcode which are printed using \p extruder_nr 373 * 374 * \param[in] storage where the slice data is stored. 375 * \param mesh The mesh to add to the layer plan \p gcode_layer. 376 * \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder 377 * \param mesh_config the line config with which to print a print feature 378 * \param gcode_layer The initial planning of the gcode of the layer. 379 */ 380 void addMeshLayerToGCode(const SliceDataStorage& storage, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, LayerPlan& gcode_layer) const; 381 382 /*! 383 * Add all features of the given extruder from a single part from a given layer of a mesh-volume to the layer plan \p gcode_layer. 384 * This only adds the features which are printed with \p extruder_nr. 385 * 386 * \param[in] storage where the slice data is stored. 387 * \param storage Storage to get global settings from. 388 * \param mesh The mesh to add to the layer plan \p gcode_layer. 389 * \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder 390 * \param mesh_config the line config with which to print a print feature 391 * \param part The part to add 392 * \param gcode_layer The initial planning of the gcode of the layer. 393 */ 394 void addMeshPartToGCode(const SliceDataStorage& storage, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, LayerPlan& gcode_layer) const; 395 396 /*! 397 * \brief Add infill for a given part in a layer plan. 398 * 399 * \param gcodeLayer The initial planning of the gcode of the layer. 400 * \param mesh The mesh for which to add to the layer plan \p gcodeLayer. 401 * \param extruder_nr The extruder for which to print all features of the 402 * mesh which should be printed with this extruder. 403 * \param mesh_config the line config with which to print a print feature. 404 * \param part The part for which to create gcode. 405 * \return Whether this function added anything to the layer plan. 406 */ 407 bool processInfill(const SliceDataStorage& storage, LayerPlan& gcodeLayer, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part) const; 408 409 /*! 410 * \brief Add thicker (multiple layers) sparse infill for a given part in a 411 * layer plan. 412 * 413 * \param gcodeLayer The initial planning of the gcode of the layer. 414 * \param mesh The mesh for which to add to the layer plan \p gcodeLayer. 415 * \param extruder_nr The extruder for which to print all features of the 416 * mesh which should be printed with this extruder. 417 * \param mesh_config The line config with which to print a print feature. 418 * \param part The part for which to create gcode. 419 * \return Whether this function added anything to the layer plan. 420 */ 421 bool processMultiLayerInfill(const SliceDataStorage& storage, LayerPlan& gcodeLayer, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part) const; 422 423 /*! 424 * \brief Add normal sparse infill for a given part in a layer. 425 * \param gcodeLayer The initial planning of the gcode of the layer. 426 * \param mesh The mesh for which to add to the layer plan \p gcodeLayer. 427 * \param extruder_nr The extruder for which to print all features of the 428 * mesh which should be printed with this extruder 429 * \param mesh_config The line config with which to print a print feature. 430 * \param part The part for which to create gcode. 431 * \return Whether this function added anything to the layer plan. 432 */ 433 bool processSingleLayerInfill(const SliceDataStorage& storage, LayerPlan& gcodeLayer, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part) const; 434 435 /*! 436 * Generate the insets for the walls of a given layer part. 437 * \param[in] storage where the slice data is stored. 438 * \param gcodeLayer The initial planning of the gcode of the layer. 439 * \param mesh The mesh for which to add to the layer plan \p gcodeLayer. 440 * \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder 441 * \param mesh_config the line config with which to print a print feature 442 * \param part The part for which to create gcode 443 * \return Whether this function added anything to the layer plan 444 */ 445 bool processInsets(const SliceDataStorage& storage, LayerPlan& gcodeLayer, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part) const; 446 447 /*! 448 * Generate the a spiralized wall for a given layer part. 449 * \param[in] storage where the slice data is stored. 450 * \param[out] gcodeLayer The initial planning of the gcode of the layer. 451 * \param mesh_config the line config with which to print a print feature 452 * \param part The part for which to create gcode 453 * \param mesh The mesh for which to add to the layer plan \p gcodeLayer. 454 */ 455 void processSpiralizedWall(const SliceDataStorage& storage, LayerPlan& gcode_layer, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, const SliceMeshStorage& mesh) const; 456 457 /*! 458 * Add the gcode of the outline gaps: the areas for thin parts in which a single perimter doesnt fit. 459 * 460 * \param gcode_layer The initial planning of the gcode of the layer. 461 * \param mesh The mesh for which to add to the layer plan \p gcode_layer. 462 * \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder 463 * \param mesh_config the line config with which to print a print feature 464 * \param part The part for which to create gcode 465 * \param[out] added_something Whether this function added anything to the layer plan 466 */ 467 void processOutlineGaps(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, bool& added_something) const; 468 469 /*! 470 * Add the gcode of the top/bottom skin of the given part and of the perimeter gaps. 471 * 472 * Perimeter gaps are handled for skin outlines and printed after the skin fill of the skin part is printed by calling \ref processSkinPart. 473 * Perimeter gaps between the walls are added to the gcode afterwards. 474 * 475 * \param[in] storage where the slice data is stored. 476 * \param gcode_layer The initial planning of the gcode of the layer. 477 * \param mesh The mesh for which to add to the layer plan \p gcode_layer. 478 * \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder 479 * \param mesh_config the line config with which to print a print feature 480 * \param part The part for which to create gcode 481 * \return Whether this function added anything to the layer plan 482 */ 483 bool processSkinAndPerimeterGaps(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part) const; 484 485 /*! 486 * Add the gcode of the top/bottom skin of the given skin part and of the perimeter gaps. 487 * 488 * Perimeter gaps are handled for the current extruder for the following features if they are printed with this extruder. 489 * - skin outlines 490 * - roofing (if concentric) 491 * - top/bottom (if concentric) 492 * They are all printed at the end of printing the skin part features which are printed with this extruder. 493 * 494 * Note that the normal perimeter gaps are printed with the outer wall extruder, 495 * while newly generated perimeter gaps 496 * are printed with the extruder with which the feature was printed which generated the gaps. 497 * 498 * \param[in] storage where the slice data is stored. 499 * \param gcode_layer The initial planning of the gcode of the layer. 500 * \param mesh The mesh for which to add to the layer plan \p gcode_layer. 501 * \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder 502 * \param mesh_config the line config with which to print a print feature 503 * \param skin_part The skin part for which to create gcode 504 * \return Whether this function added anything to the layer plan 505 */ 506 bool processSkinPart(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SkinPart& skin_part) const; 507 508 /*! 509 * Add the extra skin walls 510 * 511 * \param[in] storage where the slice data is stored. 512 * \param gcode_layer The initial planning of the gcode of the layer. 513 * \param mesh The mesh for which to add to the layer plan \p gcode_layer. 514 * \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder 515 * \param mesh_config the line config with which to print a print feature 516 * \param skin_part The skin part for which to create gcode 517 * \param[out] added_something Whether this function added anything to the layer plan 518 */ 519 void processSkinInsets(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SkinPart& skin_part, bool& added_something) const; 520 521 /*! 522 * Add the roofing which is the area inside the innermost skin inset which has air 'directly' above 523 * 524 * Perimeter gaps are generated when the pattern is concentric 525 * These gaps are generated here, but not printed here because printing all perimeter gaps at the same time is more efficient. 526 * There are already some perimeter gaps from the skin outline walls. 527 * This function adds more perimeter gaps for the roofing concentric pattern. 528 * The gaps will be filled in \ref concentric_perimeter_gaps 529 * That way we can choose the fastest route between all perimeter gaps of this skin part. 530 * 531 * \param[in] storage where the slice data is stored. 532 * \param gcode_layer The initial planning of the gcode of the layer. 533 * \param mesh The mesh for which to add to the layer plan \p gcode_layer. 534 * \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder 535 * \param mesh_config the line config with which to print a print feature 536 * \param skin_part The skin part for which to create gcode 537 * \param[out] concentric_perimeter_gaps The perimeter gaps output which are generated when the pattern is concentric 538 * \param[out] added_something Whether this function added anything to the layer plan 539 */ 540 void processRoofing(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SkinPart& skin_part, Polygons& concentric_perimeter_gaps, bool& added_something) const; 541 542 /*! 543 * Add the normal skinfill which is the area inside the innermost skin inset 544 * which doesn't have air directly above it if we're printing roofing 545 * 546 * Perimeter gaps are generated when the pattern is concentric. 547 * These gaps are generated here, but not printed here because printing all perimeter gaps at the same time is more efficient. 548 * There are already some perimeter gaps from the skin outline walls. 549 * This function adds more perimeter gaps for the skin concentric pattern. 550 * The gaps will be filled in \ref concentric_perimeter_gaps 551 * That way we can choose the fastest route between all perimeter gaps of this skin part. 552 * 553 * \param[in] storage where the slice data is stored. 554 * \param gcode_layer The initial planning of the gcode of the layer. 555 * \param mesh The mesh for which to add to the layer plan \p gcode_layer. 556 * \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder 557 * \param mesh_config the line config with which to print a print feature 558 * \param skin_part The skin part for which to create gcode 559 * \param[out] concentric_perimeter_gaps The perimeter gaps output which are generated when the pattern is concentric 560 * \param[out] added_something Whether this function added anything to the layer plan 561 */ 562 void processTopBottom(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const PathConfigStorage::MeshPathConfigs& mesh_config, const SkinPart& skin_part, Polygons& concentric_perimeter_gaps, bool& added_something) const; 563 564 /*! 565 * Process a dense skin feature like roofing or top/bottom 566 * 567 * \param[in] storage where the slice data is stored. 568 * \param gcode_layer The initial planning of the gcode of the layer. 569 * \param mesh The mesh for which to add to the layer plan \p gcode_layer. 570 * \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder 571 * \param area The area to fill 572 * \param config the line config with which to print the print feature 573 * \param pattern the pattern with which to fill the print feature 574 * \param skin_angle the angle to use for linear infill types 575 * \param skin_overlap The amount by which to expand the \p area 576 * \param skin density Sets the density of the the skin lines by adjusting the distance between them (normal skin is 1.0) 577 * \param[out] perimeter_gaps_output Optional output to store the gaps which occur if the pattern is concentric 578 * \param[out] added_something Whether this function added anything to the layer plan 579 * \param fan_speed fan speed override for this skin area 580 */ 581 void processSkinPrintFeature(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const Polygons& area, const GCodePathConfig& config, EFillMethod pattern, const AngleDegrees skin_angle, const coord_t skin_overlap, const Ratio skin_density, Polygons* perimeter_gaps_output, bool& added_something, double fan_speed = GCodePathConfig::FAN_SPEED_DEFAULT) const; 582 583 /*! 584 * Add perimeter gaps of a mesh with the given extruder. 585 * 586 * \param[in] storage where the slice data is stored. 587 * \param gcode_layer The initial planning of the gcode of the layer. 588 * \param mesh The mesh for which to add to the layer plan \p gcode_layer. 589 * \param extruder_nr The extruder for which to print all features of the mesh which should be printed with this extruder 590 * \param perimeter_gaps The generated perimeter gaps to fill 591 * \param perimeter_gap_config the line config with which to print the perimeter gaps print feature 592 * \param[out] added_something Whether this function added anything to the layer plan 593 */ 594 void processPerimeterGaps(const SliceDataStorage& storage, LayerPlan& gcode_layer, const SliceMeshStorage& mesh, const size_t extruder_nr, const Polygons& perimeter_gaps, const GCodePathConfig& perimeter_gap_config, bool& added_something) const; 595 596 /*! 597 * see if we can avoid printing a lines or zig zag style skin part in multiple segments by moving to 598 * a start point that would increase the chance that the skin will be printed in a single segment. 599 * Obviously, if the skin part contains holes then it will have to be printed in multiple segments anyway but 600 * doing this may still produce fewer skin seams or move a seam that would be across the middle of the part 601 * to a less noticeable position 602 * 603 * So, instead of this \/ We get this \/ 604 * +------+ +------+ 605 * |2///#1| |1/////| 606 * |///#//| |//////| 607 * |//#///| |//////| 608 * |/#////| |//////| 609 * |#/////| |//////| 610 * +------+ +------+ 611 * 1, 2 = start locations of skin segments 612 * # = seam 613 * 614 * \param filling_part The part which we are going to fill with a linear filling type 615 * \param filling_angle The angle of the filling lines 616 * \param last_position The position the print head is in before going to fill the part 617 * \return The location near where to start filling the part 618 */ 619 std::optional<Point> getSeamAvoidingLocation(const Polygons& filling_part, int filling_angle, Point last_position) const; 620 621 /*! 622 * Add the g-code for ironing the top surface. 623 * 624 * This produces additional low-extrusion moves that cover the top surface, 625 * in order to smooth the surface more. 626 * 627 * \param mesh The settings storage to get the ironing settings and skin 628 * angles from. 629 * \param layer The layer to process the ironing for. 630 * \param line_config The configuration of the lines to draw the ironing 631 * with. 632 * \param[out] gcode_layer The output layer to put the resulting paths in. 633 * \return Whether this function added anything to the layer plan. 634 */ 635 bool processIroning(const SliceMeshStorage& mesh, const SliceLayer& part, const GCodePathConfig& line_config, LayerPlan& gcode_layer) const; 636 637 /*! 638 * Add the support to the layer plan \p gcodeLayer of the current layer for all support parts with the given \p extruder_nr. 639 * \param[in] storage where the slice data is stored. 640 * \param gcodeLayer The initial planning of the gcode of the layer. 641 * \return whether any support was added to the layer plan 642 */ 643 bool addSupportToGCode(const SliceDataStorage& storage, LayerPlan& gcodeLayer, const size_t extruder_nr) const; 644 645 /*! 646 * Add the support lines/walls to the layer plan \p gcodeLayer of the current layer. 647 * \param[in] storage where the slice data is stored. 648 * \param gcode_layer The initial planning of the gcode of the layer. 649 * \return whether any support infill was added to the layer plan 650 */ 651 bool processSupportInfill(const SliceDataStorage& storage, LayerPlan& gcode_layer) const; 652 653 /*! 654 * Add the support roofs to the layer plan \p gcodeLayer of the current 655 * layer. 656 * 657 * \param[in] storage Where the slice data is stored. 658 * \param gcodeLayer The initial planning of the g-code of the layer. 659 * \return Whether any support skin was added to the layer plan. 660 */ 661 bool addSupportRoofsToGCode(const SliceDataStorage& storage, LayerPlan& gcodeLayer) const; 662 663 /*! 664 * Add the support bottoms to the layer plan \p gcodeLayer of the current 665 * layer. 666 * 667 * \param[in] storage Where the slice data is stored. 668 * \param gcodeLayer The initial planning of the g-code of the layer. 669 * \return Whether any support skin was added to the layer plan. 670 */ 671 bool addSupportBottomsToGCode(const SliceDataStorage& storage, LayerPlan& gcodeLayer) const; 672 673 public: 674 /*! 675 * Change to a new extruder, and add the prime tower instructions if the new extruder is different from the last. 676 * 677 * On layer 0 this function adds the skirt for the nozzle it switches to, instead of the prime tower. 678 * 679 * \param[in] storage where the slice data is stored. 680 * \param gcode_layer The initial planning of the gcode of the layer. 681 * \param extruder_nr The extruder to switch to. 682 */ 683 void setExtruder_addPrime(const SliceDataStorage& storage, LayerPlan& gcode_layer, const size_t extruder_nr) const; 684 685 private: 686 /*! 687 * Add the prime tower gcode for the current layer. 688 * \param[in] storage where the slice data is stored. 689 * \param gcodeLayer The initial planning of the gcode of the layer. 690 * \param prev_extruder The current extruder with which we last printed. 691 */ 692 void addPrimeTower(const SliceDataStorage& storage, LayerPlan& gcodeLayer, int prev_extruder) const; 693 694 /*! 695 * Add the end gcode and set all temperatures to zero. 696 */ 697 void finalize(); 698 699 /*! 700 * Calculate for each layer the index of the vertex that is considered to be the seam 701 * \param storage where the slice data is stored. 702 * \param total_layers The total number of layers 703 */ 704 void findLayerSeamsForSpiralize(SliceDataStorage& storage, size_t total_layers); 705 706 /*! 707 * Calculate the index of the vertex that is considered to be the seam for the given layer 708 * \param storage where the slice data is stored. 709 * \param mesh the mesh containing the layer of interest 710 * \param layer_nr layer number of the layer whose seam verted index is required 711 * \param last_layer_nr layer number of the previous layer 712 * \return layer seam vertex index 713 */ 714 unsigned int findSpiralizedLayerSeamVertexIndex(const SliceDataStorage& storage, const SliceMeshStorage& mesh, const int layer_nr, const int last_layer_nr); 715 }; 716 717 }//namespace cura 718 719 #endif // GCODE_WRITER_H 720