3030namespace cura
3131{
3232
33+ coord_t SkirtBrimAppender::ExtruderConfig::getLineWidth (const ConstLayerPlanPtr& layer_plan) const
34+ {
35+ return getLineWidth (layer_plan->getLayerIndex ());
36+ }
37+
3338SkirtBrimAppender::SkirtBrimAppender (const SliceDataStorage& storage) :
3439 PrintOperationTransformer ()
3540 ,storage_(storage)
@@ -57,14 +62,32 @@ void SkirtBrimAppender::process(PrintPlan* print_plan)
5762 const size_t height = calculateMaxHeight (extruders_configs, adhesion_type);
5863
5964 const std::map<ExtruderNumber, Shape> starting_outlines = generateStartingOutlines (print_plan, skirt_brim_extruder_nr, height, adhesion_type, used_extruders);
60- const std::map<ExtruderNumber, Shape> allowed_areas_per_extruder = generateAllowedAreas (starting_outlines, adhesion_type, used_extruders, skirt_brim_extruder_nr, extruders_configs);
65+ const std::map<ExtruderNumber, Shape> allowed_areas_per_extruder
66+ = generateAllowedAreas (starting_outlines, adhesion_type, used_extruders, skirt_brim_extruder_nr, extruders_configs);
6167
62- for (LayerIndex actual_height = 0 ; actual_height < height; ++actual_height)
68+ // Specific outlines that are used for upper layers of skirt and generated at first layer, first offset
69+ std::map<ExtruderNumber, Shape> specific_starting_outlines;
70+
71+ for (LayerIndex actual_height = 0 ; actual_height < height; ++actual_height)
6372 {
6473 LayerPlanPtr layer_plan = print_plan->findLayerPlan (actual_height);
6574 if (layer_plan)
6675 {
67- generateSkirtBrim (adhesion_type, used_extruders, starting_outlines, allowed_areas_per_extruder, extruders_configs, layer_plan);
76+ auto first_extruder_outline_action = FirstExtruderOutlineAction::None;
77+ if (adhesion_type == EPlatformAdhesion::SKIRT)
78+ {
79+ first_extruder_outline_action = actual_height == 0 ? FirstExtruderOutlineAction::Save : FirstExtruderOutlineAction::Use;
80+ }
81+
82+ generateSkirtBrim (
83+ adhesion_type,
84+ used_extruders,
85+ starting_outlines,
86+ specific_starting_outlines,
87+ allowed_areas_per_extruder,
88+ extruders_configs,
89+ layer_plan,
90+ first_extruder_outline_action);
6891 }
6992 }
7093}
@@ -110,8 +133,9 @@ std::map<ExtruderNumber, SkirtBrimAppender::ExtruderConfig> SkirtBrimAppender::g
110133 const Settings& settings = Application::getInstance ().current_slice_ ->scene .getExtruder (extruder_nr).settings_ ;
111134
112135 const auto & location = settings.get <BrimLocation>(" brim_location" );
113- // FIXME: Use initial_layer_line_width_factor only on first layer, and also handle the initial-layer speed and flow
114- extruder_config.line_width_ = settings.get <coord_t >(" skirt_brim_line_width" ) * settings.get <Ratio>(" initial_layer_line_width_factor" );
136+ // FIXME: Handle the initial-layer speed and flow
137+ extruder_config.line_width_X_ = settings.get <coord_t >(" skirt_brim_line_width" );
138+ extruder_config.line_width_0_ = extruder_config.line_width_X_ * settings.get <Ratio>(" initial_layer_line_width_factor" );
115139 extruder_config.skirt_brim_minimal_length_ = settings.get <coord_t >(" skirt_brim_minimal_length" );
116140 extruder_config.outside_polys_ = adhesion_type == EPlatformAdhesion::SKIRT || (location & BrimLocation::OUTSIDE);
117141 extruder_config.inside_polys_ = adhesion_type == EPlatformAdhesion::BRIM && (location & BrimLocation::INSIDE);
@@ -222,7 +246,7 @@ std::map<ExtruderNumber, Shape> SkirtBrimAppender::generateAllowedAreas(
222246 for (size_t other_extruder_nr = 0 ; other_extruder_nr < covered_area_by_extruder.size (); ++other_extruder_nr)
223247 {
224248 const ExtruderOutlines& extruder_outlines = covered_area_by_extruder[other_extruder_nr];
225- const coord_t base_offset = extruder_config.line_width_ / 2 ;
249+ const coord_t base_offset = extruder_config.line_width_0_ / 2 ;
226250
227251 // Remove areas covered by models
228252 for (const Polygon& covered_surface : extruder_outlines.models_outlines )
@@ -276,9 +300,11 @@ std::vector<ContinuousExtruderMoveSequencePtr> SkirtBrimAppender::generateOffset
276300 Shape& covered_area,
277301 std::map<ExtruderNumber, Shape>& allowed_areas_per_extruder,
278302 const std::map<ExtruderNumber, ExtruderConfig>& extruders_configs,
279- const LayerPlanPtr &layer_plan)
303+ const LayerPlanPtr &layer_plan,
304+ const bool update_allowed_areas)
280305{
281306 const ExtruderConfig &extruder_config = extruders_configs.at (extruder_nr);
307+ const coord_t line_width = extruder_config.getLineWidth (layer_plan);
282308
283309 Shape brim = covered_area.offset (total_offset, ClipperLib::jtRound);
284310
@@ -287,9 +313,9 @@ std::vector<ContinuousExtruderMoveSequencePtr> SkirtBrimAppender::generateOffset
287313
288314 OpenLinesSet brim_lines = allowed_areas_per_extruder[extruder_nr].intersection (brim, false );
289315
290- Shape newly_covered = brim_lines.offset ((extruder_config. line_width_ / 2 ) + 10 , ClipperLib::jtRound);
316+ Shape newly_covered = brim_lines.offset ((line_width / 2 ) + 10 , ClipperLib::jtRound);
291317
292- const coord_t max_stitch_distance = extruder_config. line_width_ ;
318+ const coord_t max_stitch_distance = line_width ;
293319 MixedLinesSet result;
294320 MixedPolylineStitcher::stitch (brim_lines, result, max_stitch_distance);
295321
@@ -300,15 +326,17 @@ std::vector<ContinuousExtruderMoveSequencePtr> SkirtBrimAppender::generateOffset
300326 {
301327 if (extrusion_line->length () >= min_brim_line_length_)
302328 {
303- extrusions.push_back (ContinuousExtruderMoveSequence::makeFrom (*extrusion_line, extruder_config. line_width_ , config.getSpeed ()));
329+ extrusions.push_back (ContinuousExtruderMoveSequence::makeFrom (*extrusion_line, line_width , config.getSpeed ()));
304330 }
305331 }
306332
307- // update allowed_areas_per_extruder
308- covered_area = covered_area.unionPolygons (newly_covered.unionPolygons ());
309- for (Shape& allowed_area : ranges::views::values (allowed_areas_per_extruder))
333+ if (update_allowed_areas)
310334 {
311- allowed_area = allowed_area.difference (covered_area);
335+ covered_area = covered_area.unionPolygons (newly_covered.unionPolygons ());
336+ for (Shape& allowed_area : ranges::views::values (allowed_areas_per_extruder))
337+ {
338+ allowed_area = allowed_area.difference (covered_area);
339+ }
312340 }
313341
314342 return extrusions;
@@ -332,9 +360,11 @@ void SkirtBrimAppender::generateSkirtBrim(
332360 const EPlatformAdhesion adhesion_type,
333361 std::vector<ExtruderNumber>& used_extruders,
334362 const std::map<ExtruderNumber, Shape>& starting_outlines,
363+ std::map<ExtruderNumber, Shape>& specific_starting_outlines,
335364 std::map<ExtruderNumber, Shape> allowed_areas_per_extruder,
336365 const std::map<ExtruderNumber, ExtruderConfig>& extruders_configs,
337- const LayerPlanPtr& layer_plan)
366+ const LayerPlanPtr& layer_plan,
367+ const FirstExtruderOutlineAction first_extruder_outline_action)
338368{
339369 struct ExtruderOffsetData
340370 {
@@ -356,22 +386,22 @@ void SkirtBrimAppender::generateSkirtBrim(
356386 {
357387 extruder_offset_datas.push_back (ExtruderOffsetData{
358388 .extruder_nr = extruder_nr,
359- .extrusion = std::make_shared<FeatureExtrusion>(PrintFeatureType::SkirtBrim, extruder_config.line_width_ )
389+ .extrusion = std::make_shared<FeatureExtrusion>(PrintFeatureType::SkirtBrim, extruder_config.getLineWidth (layer_plan) )
360390 });
361391 }
362392 }
363393
364394 // Create a cache containing the extruders processing ordering, we are going to need it extensively
365395 const std::map<ExtruderNumber, size_t > extruder_ordering = [&used_extruders]()
366396 {
367- std::map<ExtruderNumber, size_t > extruder_ordering ;
397+ std::map<ExtruderNumber, size_t > extruder_ordering_tmp ;
368398
369399 for (const auto & [index, extruder_number] : used_extruders | ranges::views::enumerate)
370400 {
371- extruder_ordering [extruder_number] = index;
401+ extruder_ordering_tmp [extruder_number] = index;
372402 }
373403
374- return extruder_ordering ;
404+ return extruder_ordering_tmp ;
375405 }();
376406
377407 std::map<ExtruderNumber, Shape> covered_areas = starting_outlines;
@@ -395,17 +425,36 @@ void SkirtBrimAppender::generateSkirtBrim(
395425 ExtruderOffsetData &extruder_offset_data = *iterator;
396426 const ExtruderNumber extruder_nr = extruder_offset_data.extruder_nr ;
397427 const ExtruderConfig &extruder_config = extruders_configs.at (extruder_nr);
428+
429+ Shape *starting_outline;
430+ if (first_extruder_outline_action == FirstExtruderOutlineAction::Use)
431+ {
432+ starting_outline = &specific_starting_outlines[extruder_nr];
433+ }
434+ else
435+ {
436+ starting_outline = &covered_areas.at (adhesion_type == EPlatformAdhesion::SKIRT ? 0 : extruder_nr);
437+ }
438+
439+ if (extruder_offset_data.processed_offsets == 0 && first_extruder_outline_action == FirstExtruderOutlineAction::Save)
440+ {
441+ specific_starting_outlines[extruder_nr] = *starting_outline;
442+ }
443+
398444 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 );
445+ const coord_t offset = (extruder_config.getLineWidth (layer_plan) / 2 ) + (add_gap ? extruder_config.gap_ : 0 );
400446 extruder_offset_data.processed_offsets ++;
401447 extruder_offset_data.total_offset += offset;
448+
449+ const bool update_allowed_areas = first_extruder_outline_action != FirstExtruderOutlineAction::Use;
402450 const std::vector<ContinuousExtruderMoveSequencePtr> offset_extrusions = generateOffset (
403451 extruder_nr,
404452 offset,
405- covered_areas. at (adhesion_type == EPlatformAdhesion::SKIRT ? 0 : extruder_nr) ,
453+ *starting_outline ,
406454 allowed_areas_per_extruder,
407455 extruders_configs,
408- layer_plan);
456+ layer_plan,
457+ update_allowed_areas);
409458
410459 for (const ContinuousExtruderMoveSequencePtr& offset_extrusion : offset_extrusions)
411460 {
0 commit comments