@@ -568,14 +568,32 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
568568 const double fan_speed,
569569 const bool travel_to_z)
570570{
571- const auto add_extrusion_move = [&](const Point3LL& target, const Ratio& overhang_speed_factor = 1 .0_r )
571+ const auto add_extrusion_move = [&](const Point3LL& target, const std::optional< size_t > speed_region_index = std:: nullopt )
572572 {
573+ const Ratio overhang_speed_factor = speed_region_index.has_value () ? overhang_masks_[speed_region_index.value ()].speed_ratio : 1 .0_r;
573574 addExtrusionMove (target, config, space_fill_type, flow, width_factor, spiralize, speed_factor * overhang_speed_factor, fan_speed, travel_to_z);
574575 };
575576
577+ const auto update_is_overhanging = [this ](const Point2LL& target, std::optional<Point2LL> current_position, const bool is_overhanging = false )
578+ {
579+ if (is_overhanging != currently_overhanging_)
580+ {
581+ max_overhang_length_ = std::max (current_overhang_length_, max_overhang_length_);
582+ current_overhang_length_ = 0 ;
583+ }
584+
585+ if (is_overhanging && current_position.has_value ())
586+ {
587+ current_overhang_length_ += vSize (target - current_position.value ());
588+ }
589+
590+ currently_overhanging_ = is_overhanging;
591+ };
592+
576593 if (overhang_masks_.empty () || ! last_planned_position_.has_value ())
577594 {
578595 // Unable to apply gradual overhanging (probably just disabled), just add the basic extrusion move
596+ update_is_overhanging (p.toPoint2LL (), last_planned_position_);
579597 add_extrusion_move (p);
580598 return ;
581599 }
@@ -619,7 +637,13 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
619637 }
620638 };
621639
622- const std::vector<SVG::Color> colors = { SVG::Color::RED, SVG::Color::GREEN, SVG::Color::BLUE, SVG::Color::YELLOW };
640+ struct SegmentExtrusionMove
641+ {
642+ Point2LL position;
643+ size_t speed_region_index;
644+ };
645+
646+ std::vector<SegmentExtrusionMove> extrusion_moves;
623647
624648 // Now move along segment and split it where we cross speed regions
625649 while (true )
@@ -658,7 +682,7 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
658682
659683 // Move to intersection at current region speed
660684 const Point2LL split_position = start + vector * intersection_parameter;
661- add_extrusion_move ( split_position, overhang_masks_[ actual_speed_region_index]. speed_ratio );
685+ extrusion_moves. push_back (SegmentExtrusionMove{ split_position, actual_speed_region_index } );
662686
663687 // Prepare for next move in different region
664688 actual_speed_region_index = next_speed_region_index;
@@ -667,10 +691,68 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
667691 else
668692 {
669693 // We cross no border, which means we can reach the end of the segment within the current speed region, so we are done
670- add_extrusion_move (p, overhang_masks_[actual_speed_region_index].speed_ratio );
671- return ;
694+ extrusion_moves.push_back (SegmentExtrusionMove{ p.toPoint2LL (), actual_speed_region_index });
695+ break ;
696+ }
697+ }
698+
699+ // Filter out micro-segments
700+ std::vector<SegmentExtrusionMove> extrusion_moves_filtered;
701+ extrusion_moves_filtered.reserve (extrusion_moves.size ());
702+ Point2LL current_position = start;
703+ for (const SegmentExtrusionMove& extrusion_move : extrusion_moves | ranges::views::drop_last (1 ))
704+ {
705+ if (vSize2 (extrusion_move.position - current_position) >= MINIMUM_SQUARED_LINE_LENGTH)
706+ {
707+ extrusion_moves_filtered.push_back (extrusion_move);
708+ }
709+
710+ current_position = extrusion_move.position ;
711+ }
712+
713+ if (extrusion_moves_filtered.empty () || vSize2 (extrusion_moves.back ().position - current_position) >= MINIMUM_SQUARED_LINE_LENGTH)
714+ {
715+ extrusion_moves_filtered.push_back (extrusion_moves.back ());
716+ }
717+ else
718+ {
719+ extrusion_moves_filtered.back ().position = extrusion_moves.back ().position ;
720+ }
721+
722+ // Calculate max consecutive overhanging segment length
723+ current_position = start;
724+ for (const SegmentExtrusionMove& extrusion_move : extrusion_moves_filtered)
725+ {
726+ const bool is_overhanging = extrusion_move.speed_region_index > 0 ;
727+ update_is_overhanging (extrusion_move.position , current_position, is_overhanging);
728+ current_position = extrusion_move.position ;
729+ }
730+
731+ // Merge consecutive sub-segments that in the end have the same speed
732+ std::vector<SegmentExtrusionMove> extrusion_moves_merged;
733+ extrusion_moves_merged.reserve (extrusion_moves_filtered.size ());
734+ extrusion_moves_merged.push_back (extrusion_moves_filtered.front ());
735+
736+ for (const SegmentExtrusionMove& extrusion_move : extrusion_moves_filtered | ranges::views::drop (1 ))
737+ {
738+ const Ratio previous_speed_factor = overhang_masks_[extrusion_moves_merged.back ().speed_region_index ].speed_ratio ;
739+ const Ratio next_speed_factor = overhang_masks_[extrusion_move.speed_region_index ].speed_ratio ;
740+
741+ if (next_speed_factor == previous_speed_factor)
742+ {
743+ extrusion_moves_merged.back ().position = extrusion_move.position ;
744+ }
745+ else
746+ {
747+ extrusion_moves_merged.push_back (extrusion_move);
672748 }
673749 }
750+
751+ // Finally, add extrusion moves
752+ for (const SegmentExtrusionMove& extrusion_move : extrusion_moves_merged)
753+ {
754+ add_extrusion_move (extrusion_move.position , extrusion_move.speed_region_index );
755+ }
674756}
675757
676758template <class PathType >
@@ -2561,7 +2643,11 @@ void LayerPlan::processFanSpeedAndMinimalLayerTime(Point2LL starting_position)
25612643 {
25622644 other_extr_plan_time += extruder_plan.estimates_ .getTotalTime ();
25632645 }
2564- maximum_cool_min_layer_time = std::max (maximum_cool_min_layer_time, extruder_plan.fan_speed_layer_time_settings_ .cool_min_layer_time );
2646+
2647+ const FanSpeedLayerTimeSettings& settings = extruder_plan.fan_speed_layer_time_settings_ ;
2648+ const bool apply_minimum_layer_time_overhang = max_overhang_length_ > settings.cool_min_layer_time_overhang_min_segment_length ;
2649+ maximum_cool_min_layer_time
2650+ = std::max (maximum_cool_min_layer_time, apply_minimum_layer_time_overhang ? settings.cool_min_layer_time_overhang : settings.cool_min_layer_time );
25652651
25662652 // Modify fan speeds for the first layer(s)
25672653 extruder_plan.processFanSpeedForFirstLayers ();
0 commit comments