@@ -51,9 +51,7 @@ void SkirtBrimAppender::process(PrintPlan* print_plan)
5151 const std::optional<ExtruderNumber> skirt_brim_extruder_nr = skirt_brim_extruder_nr_setting >= 0 ? std::make_optional (skirt_brim_extruder_nr_setting) : std::nullopt ;
5252
5353 // Get the first extruder plan for each extruder
54- std::vector<ConstExtruderPlanPtr> first_extruder_plans;
55- ExtrudersSet used_extruders;
56- std::tie (first_extruder_plans, used_extruders) = generateUsedExtruders (print_plan);
54+ std::vector<ExtruderNumber> used_extruders = generateUsedExtruders (print_plan);
5755
5856 const std::map<ExtruderNumber, ExtruderConfig> extruders_configs = generateExtrudersConfigs (used_extruders, adhesion_type);
5957 const size_t height = calculateMaxHeight (extruders_configs, adhesion_type);
@@ -66,30 +64,28 @@ void SkirtBrimAppender::process(PrintPlan* print_plan)
6664 LayerPlanPtr layer_plan = print_plan->findLayerPlan (actual_height);
6765 if (layer_plan)
6866 {
69- generateSkirtBrim (adhesion_type, used_extruders, first_extruder_plans, starting_outlines, allowed_areas_per_extruder, extruders_configs, layer_plan);
67+ generateSkirtBrim (adhesion_type, used_extruders, starting_outlines, allowed_areas_per_extruder, extruders_configs, layer_plan);
7068 }
7169 }
7270}
7371
74- std::tuple<std:: vector<ConstExtruderPlanPtr>, ExtrudersSet > SkirtBrimAppender::generateUsedExtruders (const PrintPlan* print_plan)
72+ std::vector<ExtruderNumber > SkirtBrimAppender::generateUsedExtruders (const PrintPlan* print_plan)
7573{
76- std::vector<ConstExtruderPlanPtr> first_extruder_plans;
77- ExtrudersSet used_extruders;
74+ std::vector<ExtruderNumber> used_extruders;
7875
7976 print_plan->applyOnOperationsByType <ExtruderPlan>(
80- [&first_extruder_plans, & used_extruders](const ConstExtruderPlanPtr& extruder_plan)
77+ [&used_extruders](const ConstExtruderPlanPtr& extruder_plan)
8178 {
8279 const ExtruderNumber extruder_nr = extruder_plan->getExtruderNr ();
83- if (! used_extruders. contains (extruder_nr))
80+ if (! ranges:: contains (used_extruders, extruder_nr))
8481 {
85- first_extruder_plans.push_back (extruder_plan);
86- used_extruders.set (extruder_nr);
82+ used_extruders.push_back (extruder_nr);
8783 }
8884 },
8985 PrintOperationSequence::SearchOrder::Forward,
9086 2 );
9187
92- return std::make_tuple (first_extruder_plans, used_extruders) ;
88+ return used_extruders;
9389}
9490
9591size_t SkirtBrimAppender::calculateMaxHeight (const std::map<ExtruderNumber, ExtruderConfig>& extruders_configs, const EPlatformAdhesion adhesion_type)
@@ -104,7 +100,7 @@ size_t SkirtBrimAppender::calculateMaxHeight(const std::map<ExtruderNumber, Extr
104100 return height;
105101}
106102
107- std::map<ExtruderNumber, SkirtBrimAppender::ExtruderConfig> SkirtBrimAppender::generateExtrudersConfigs (const ExtrudersSet & used_extruders, const EPlatformAdhesion adhesion_type)
103+ std::map<ExtruderNumber, SkirtBrimAppender::ExtruderConfig> SkirtBrimAppender::generateExtrudersConfigs (std::vector<ExtruderNumber> & used_extruders, const EPlatformAdhesion adhesion_type)
108104{
109105 std::map<ExtruderNumber, ExtruderConfig> extruders_configs;
110106
@@ -130,10 +126,10 @@ std::map<ExtruderNumber, SkirtBrimAppender::ExtruderConfig> SkirtBrimAppender::g
130126
131127std::map<size_t , Shape> SkirtBrimAppender::generateStartingOutlines (
132128 const PrintPlan* print_plan,
133- const std::optional<ExtruderNumber> skirt_brim_extruder_nr ,
129+ const std::optional<ExtruderNumber> brim_extruder_nr ,
134130 const size_t height,
135131 const EPlatformAdhesion adhesion_type,
136- const ExtrudersSet & used_extruders)
132+ std::vector<ExtruderNumber> & used_extruders)
137133{
138134 // Calculate the united footprints of all the extrusion features on the first layers
139135 std::map<ExtruderNumber, std::vector<Shape>> features_footprints;
@@ -143,7 +139,7 @@ std::map<size_t, Shape> SkirtBrimAppender::generateStartingOutlines(
143139 {
144140 for (const ConstExtruderPlanPtr &extruder_plan :layer_plan->getOperationsAs <ExtruderPlan>())
145141 {
146- const ExtruderNumber target_extruder_nr = adhesion_type == EPlatformAdhesion::SKIRT ? 0 : skirt_brim_extruder_nr .value_or (extruder_plan->getExtruderNr ());
142+ const ExtruderNumber target_extruder_nr = adhesion_type == EPlatformAdhesion::SKIRT ? 0 : brim_extruder_nr .value_or (extruder_plan->getExtruderNr ());
147143 std::vector<Shape> &target_footprints = features_footprints[target_extruder_nr];
148144
149145 for (const ConstFeatureExtrusionPtr& feature_extrusion : extruder_plan->getOperationsAs <FeatureExtrusion>())
@@ -175,7 +171,7 @@ std::map<size_t, Shape> SkirtBrimAppender::generateStartingOutlines(
175171std::map<ExtruderNumber, Shape> SkirtBrimAppender::generateAllowedAreas (
176172 const std::map<ExtruderNumber, Shape>& starting_outlines,
177173 const EPlatformAdhesion adhesion_type,
178- const ExtrudersSet &used_extruders,
174+ std::vector<ExtruderNumber> &used_extruders,
179175 const std::optional<ExtruderNumber> skirt_brim_extruder_nr,
180176 const std::map<ExtruderNumber, ExtruderConfig>& extruders_configs) const
181177{
@@ -214,14 +210,13 @@ std::map<ExtruderNumber, Shape> SkirtBrimAppender::generateAllowedAreas(
214210 std::map<ExtruderNumber, Shape> allowed_areas_per_extruder;
215211 for (const ExtruderNumber extruder_nr : used_extruders)
216212 {
217- const ExtruderConfig& extruder_config = extruders_configs.at (extruder_nr);
218-
219213 // Initialize allowed area to full build plate, then remove disallowed areas
220214 Shape& allowed_areas = allowed_areas_per_extruder[extruder_nr];
221215 allowed_areas = storage_.getMachineBorder (extruder_nr);
222216
223217 if (adhesion_type == EPlatformAdhesion::BRIM)
224218 {
219+ const ExtruderConfig& extruder_config = extruders_configs.at (extruder_nr);
225220 const coord_t hole_brim_distance = extruder_config.brim_inside_margin_ ;
226221
227222 for (size_t other_extruder_nr = 0 ; other_extruder_nr < covered_area_by_extruder.size (); ++other_extruder_nr)
@@ -264,20 +259,24 @@ std::map<ExtruderNumber, Shape> SkirtBrimAppender::generateAllowedAreas(
264259 }
265260
266261 // Anyway, don't allow a brim/skirt to grow inside itself, which may happen e.g. with ooze shield+skirt
267- const Shape starting_outline = starting_outlines.at (extruder_nr);
268- allowed_areas = allowed_areas.difference (starting_outline.offset (extruder_config.gap_ - 50 , ClipperLib::jtRound));
262+ const Shape starting_outline = starting_outlines.at (adhesion_type == EPlatformAdhesion::SKIRT ? 0 : extruder_nr);
263+
264+ // When using a skirt, the used gap will be the one of the first processed extruder
265+ const ExtruderNumber gap_extruder_nr = adhesion_type == EPlatformAdhesion::SKIRT ? used_extruders.front () : extruder_nr;
266+ const coord_t gap = extruders_configs.at (gap_extruder_nr).gap_ ;
267+ allowed_areas = allowed_areas.difference (starting_outline.offset (gap - 50 , ClipperLib::jtRound));
269268 }
270269
271270 return allowed_areas_per_extruder;
272271}
273272
274273std::vector<ContinuousExtruderMoveSequencePtr> SkirtBrimAppender::generateOffset (
275- const ExtruderNumber extruder_nr,
276- const coord_t total_offset,
277- Shape& covered_area,
278- std::map<ExtruderNumber, Shape>& allowed_areas_per_extruder,
279- const std::map<ExtruderNumber, ExtruderConfig>& extruders_configs,
280- const LayerPlanPtr &layer_plan)
274+ const ExtruderNumber extruder_nr,
275+ const coord_t total_offset,
276+ Shape& covered_area,
277+ std::map<ExtruderNumber, Shape>& allowed_areas_per_extruder,
278+ const std::map<ExtruderNumber, ExtruderConfig>& extruders_configs,
279+ const LayerPlanPtr &layer_plan)
281280{
282281 const ExtruderConfig &extruder_config = extruders_configs.at (extruder_nr);
283282
@@ -331,8 +330,7 @@ std::vector<ContinuousExtruderMoveSequencePtr> SkirtBrimAppender::generateOffset
331330
332331void SkirtBrimAppender::generateSkirtBrim (
333332 const EPlatformAdhesion adhesion_type,
334- const ExtrudersSet &used_extruders,
335- const std::vector<ConstExtruderPlanPtr> first_extruder_plans,
333+ std::vector<ExtruderNumber>& used_extruders,
336334 const std::map<ExtruderNumber, Shape>& starting_outlines,
337335 std::map<ExtruderNumber, Shape> allowed_areas_per_extruder,
338336 const std::map<ExtruderNumber, ExtruderConfig>& extruders_configs,
@@ -341,62 +339,70 @@ void SkirtBrimAppender::generateSkirtBrim(
341339 struct ExtruderOffsetData
342340 {
343341 ExtruderNumber extruder_nr;
344- coord_t next_offset;
345342 FeatureExtrusionPtr extrusion;
343+ coord_t total_offset{0 };
346344 coord_t extruded_length{0 };
347345 bool done{false };
348346 size_t processed_offsets{0 };
349347 };
350348
351- // Create a map containing the processing data for each extruder to be processed
349+ // Create a vector containing the processing data for each extruder to be processed,
350+ // ordered in actual processing order
352351 std::vector<ExtruderOffsetData> extruder_offset_datas;
353352 for (const ExtruderNumber extruder_nr : used_extruders)
354353 {
355354 const ExtruderConfig &extruder_config = extruders_configs.at (extruder_nr);
356355 if (extruder_config.skirt_height_ > layer_plan->getLayerIndex ())
357356 {
358- const coord_t first_offset = extruder_config.gap_ + (extruder_config.line_width_ / 2 );
359357 extruder_offset_datas.push_back (ExtruderOffsetData{
360358 .extruder_nr = extruder_nr,
361- .next_offset = first_offset,
362359 .extrusion = std::make_shared<FeatureExtrusion>(PrintFeatureType::SkirtBrim, extruder_config.line_width_ )
363360 });
364361 }
365362 }
366363
367364 // Create a cache containing the extruders processing ordering, we are going to need it extensively
368- const std::map<ExtruderNumber, size_t > extruder_ordering = [&first_extruder_plans ]()
365+ const std::map<ExtruderNumber, size_t > extruder_ordering = [&used_extruders ]()
369366 {
370- size_t ordering = 0 ;
371367 std::map<ExtruderNumber, size_t > extruder_ordering;
372- for (const ConstExtruderPlanPtr &extruder_plan : first_extruder_plans)
368+
369+ for (const auto & [index, extruder_number] : used_extruders | ranges::views::enumerate)
373370 {
374- extruder_ordering[extruder_plan-> getExtruderNr () ] = ordering++ ;
371+ extruder_ordering[extruder_number ] = index ;
375372 }
373+
376374 return extruder_ordering;
377375 }();
378376
379377 std::map<ExtruderNumber, Shape> covered_areas = starting_outlines;
378+ bool first_offset = true ;
380379
381380 while (!ranges::all_of (extruder_offset_datas, [](const ExtruderOffsetData &data) {return data.done ;}))
382381 {
383- auto iterator = ranges::min_element (extruder_offset_datas, [&extruder_ordering](const auto &offset1, const auto & offset2)
382+ auto iterator = ranges::min_element (extruder_offset_datas, [&extruder_ordering, &adhesion_type ](const auto &offset1, const auto & offset2)
384383 {
385- if (offset1.next_offset == offset2.next_offset )
384+ if (! offset1.done && ! offset2.done )
386385 {
387- return extruder_ordering.at (offset1.extruder_nr ) < extruder_ordering.at (offset2.extruder_nr );
386+ if (adhesion_type == EPlatformAdhesion::SKIRT || offset1.total_offset == offset2.total_offset )
387+ {
388+ return extruder_ordering.at (offset1.extruder_nr ) < extruder_ordering.at (offset2.extruder_nr );
389+ }
390+ return offset1.total_offset < offset2.total_offset ;
388391 }
389- return offset1.next_offset < offset2. next_offset ;
392+ return ! offset1.done ;
390393 });
391394
392395 ExtruderOffsetData &extruder_offset_data = *iterator;
393- extruder_offset_data.processed_offsets ++;
394396 const ExtruderNumber extruder_nr = extruder_offset_data.extruder_nr ;
395397 const ExtruderConfig &extruder_config = extruders_configs.at (extruder_nr);
398+ const bool add_gap = (adhesion_type == EPlatformAdhesion::SKIRT) ? first_offset : (extruder_offset_data.processed_offsets == 0 );
399+ const coord_t offset = (extruder_config.line_width_ / 2 ) + (add_gap ? extruder_config.gap_ : 0 );
400+ extruder_offset_data.processed_offsets ++;
401+ extruder_offset_data.total_offset += offset;
396402 const std::vector<ContinuousExtruderMoveSequencePtr> offset_extrusions = generateOffset (
397403 extruder_nr,
398- extruder_offset_data. next_offset ,
399- covered_areas.at (extruder_nr),
404+ offset ,
405+ covered_areas.at (adhesion_type == EPlatformAdhesion::SKIRT ? 0 : extruder_nr),
400406 allowed_areas_per_extruder,
401407 extruders_configs,
402408 layer_plan);
@@ -407,20 +413,31 @@ void SkirtBrimAppender::generateSkirtBrim(
407413 extruder_offset_data.extruded_length += offset_extrusion->calculateLength ();
408414 }
409415
410- extruder_offset_data.next_offset = extruder_config.line_width_ / 2 ;
411-
412416 if (offset_extrusions.empty () ||
413417 layer_plan->getLayerIndex () > 0 ||
414418 (extruder_offset_data.processed_offsets >= extruder_config.line_count_ && extruder_offset_data.extruded_length >= extruder_config.skirt_brim_minimal_length_ ))
415419 {
416420 extruder_offset_data.done = true ;
417421 }
422+
423+ first_offset = false ;
418424 }
419425
420- for (auto & extrusion : extruder_offset_datas)
426+ // Now add the generated feature to the proper extruder plans
427+ for (auto & extruder_offset_data : extruder_offset_datas)
421428 {
422- const auto &feature = extrusion.extrusion ;
423- layer_plan->getOperationsAs <ExtruderPlan>().front ()->appendFeatureExtrusion (feature);
429+ const auto &feature_extrusion = extruder_offset_data.extrusion ;
430+ const ExtruderNumber extruder_nr = extruder_offset_data.extruder_nr ;
431+ ExtruderPlanPtr extruder_plan = layer_plan->findFirstExtruderPlan (extruder_nr);
432+ if (!extruder_plan)
433+ {
434+ // FIXME: Find a way to easily create an extruder plan (maybe it should not contain the travel speeds)
435+ const SpeedDerivatives& travel_speed = layer_plan->getConfigsStorage ()->travel_config_per_extruder [extruder_nr].speed_derivatives ;
436+ extruder_plan = std::make_shared<ExtruderPlan>(extruder_nr, travel_speed);
437+ }
438+
439+ extruder_plan->appendFeatureExtrusion (feature_extrusion);
440+ layer_plan->appendExtruderPlan (extruder_plan);
424441 }
425442}
426443
0 commit comments