@@ -57,14 +57,15 @@ GCodePath* LayerPlan::getLatestPathWithConfig(
5757 {
5858 return &paths.back ();
5959 }
60- paths.emplace_back (GCodePath{ .z_offset = z_offset,
61- .config = config,
62- .mesh = current_mesh_,
63- .space_fill_type = space_fill_type,
64- .flow = flow,
65- .width_factor = width_factor,
66- .spiralize = spiralize,
67- .speed_factor = speed_factor });
60+ paths.emplace_back (
61+ GCodePath{ .z_offset = z_offset,
62+ .config = config,
63+ .mesh = current_mesh_,
64+ .space_fill_type = space_fill_type,
65+ .flow = flow,
66+ .width_factor = width_factor,
67+ .spiralize = spiralize,
68+ .speed_factor = speed_factor });
6869
6970 GCodePath* ret = &paths.back ();
7071 ret->skip_agressive_merge_hint = mode_skip_agressive_merge_;
@@ -571,28 +572,29 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
571572 const auto add_extrusion_move = [&](const Point3LL& target, const std::optional<size_t > speed_region_index = std::nullopt )
572573 {
573574 const Ratio overhang_speed_factor = speed_region_index.has_value () ? overhang_masks_[speed_region_index.value ()].speed_ratio : 1 .0_r;
575+ addExtrusionMove (target, config, space_fill_type, flow, width_factor, spiralize, speed_factor * overhang_speed_factor, fan_speed, travel_to_z);
576+ };
574577
575- const bool is_overhanging = speed_region_index. has_value () && speed_region_index. value () > 0 ;
576-
578+ const auto update_is_overhanging = [ this ]( const Point2LL& target, std::optional<Point2LL> current_position, const bool is_overhanging = false )
579+ {
577580 if (is_overhanging != currently_overhanging_)
578581 {
579582 max_overhang_length_ = std::max (current_overhang_length_, max_overhang_length_);
580583 current_overhang_length_ = 0 ;
581584 }
582585
583- if (is_overhanging && last_planned_position_ .has_value ())
586+ if (is_overhanging && current_position .has_value ())
584587 {
585- current_overhang_length_ += vSize (target. toPoint2LL () - last_planned_position_ .value ());
588+ current_overhang_length_ += vSize (target - current_position .value ());
586589 }
587590
588591 currently_overhanging_ = is_overhanging;
589-
590- addExtrusionMove (target, config, space_fill_type, flow, width_factor, spiralize, speed_factor * overhang_speed_factor, fan_speed, travel_to_z);
591592 };
592593
593594 if (overhang_masks_.empty () || ! last_planned_position_.has_value ())
594595 {
595596 // Unable to apply gradual overhanging (probably just disabled), just add the basic extrusion move
597+ update_is_overhanging (p.toPoint2LL (), last_planned_position_);
596598 add_extrusion_move (p);
597599 return ;
598600 }
@@ -612,40 +614,12 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
612614 // Pre-calculate the intersections of the segment with all regions (except last one, you cannot intersect an infinite plane)
613615 const Point2LL end = p.toPoint2LL ();
614616 const Point2LL vector = end - start;
615- const coord_t segment_length = vSize (vector);
616617 std::vector<std::vector<float >> speed_regions_intersections;
617618 speed_regions_intersections.reserve (overhang_masks_.size () - 1 );
618619 for (const OverhangMask& overhang_region : overhang_masks_ | ranges::views::drop_last (1 ))
619620 {
620621 std::vector<float > intersections = overhang_region.supported_region .intersectionsWithSegment (start, end);
621622 ranges::sort (intersections);
622-
623- // Avoid microsegments: Move intersections that are too close to the start or end of the segment slightly more to the center of the segment.
624- for (float & intersection : intersections)
625- {
626- if (intersection * segment_length < MINIMUM_LINE_LENGTH)
627- {
628- intersection = MINIMUM_LINE_LENGTH / static_cast <float >(segment_length);
629- }
630- else if (intersection * segment_length > segment_length - MINIMUM_LINE_LENGTH)
631- {
632- intersection = (segment_length - MINIMUM_LINE_LENGTH) / static_cast <float >(segment_length);
633- }
634- }
635-
636- // (Also) Avoid microsegments: Filter out pairs of intersections that are too close to each other.
637- // This should be possible because the intersections happen in the same region.
638- constexpr std::array<float , 1 > dummy = { 2 .0f };
639- std::vector<float > temp_intersections;
640- for (const auto & tup : ranges::views::concat (dummy, intersections, dummy) | ranges::views::sliding (3 ))
641- {
642- if (std::abs (tup[1 ] - tup[0 ]) * segment_length >= MINIMUM_LINE_LENGTH && std::abs (tup[2 ] - tup[1 ]) * segment_length >= MINIMUM_LINE_LENGTH)
643- {
644- temp_intersections.push_back (tup[1 ]);
645- }
646- }
647- intersections = temp_intersections;
648-
649623 speed_regions_intersections.push_back (intersections);
650624 }
651625
@@ -664,6 +638,14 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
664638 }
665639 };
666640
641+ struct SegmentExtrusionMove
642+ {
643+ Point2LL position;
644+ size_t speed_region_index;
645+ };
646+
647+ std::vector<SegmentExtrusionMove> extrusion_moves;
648+
667649 // Now move along segment and split it where we cross speed regions
668650 while (true )
669651 {
@@ -701,7 +683,7 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
701683
702684 // Move to intersection at current region speed
703685 const Point2LL split_position = start + vector * intersection_parameter;
704- add_extrusion_move ( split_position, actual_speed_region_index);
686+ extrusion_moves. push_back (SegmentExtrusionMove{ split_position, actual_speed_region_index } );
705687
706688 // Prepare for next move in different region
707689 actual_speed_region_index = next_speed_region_index;
@@ -710,9 +692,67 @@ void LayerPlan::addExtrusionMoveWithGradualOverhang(
710692 else
711693 {
712694 // We cross no border, which means we can reach the end of the segment within the current speed region, so we are done
713- add_extrusion_move (p, actual_speed_region_index);
714- return ;
695+ extrusion_moves.push_back (SegmentExtrusionMove{ p.toPoint2LL (), actual_speed_region_index });
696+ break ;
697+ }
698+ }
699+
700+ // Filter out micro-segments
701+ std::vector<SegmentExtrusionMove> extrusion_moves_filtered;
702+ extrusion_moves_filtered.reserve (extrusion_moves.size ());
703+ Point2LL current_position = start;
704+ for (const SegmentExtrusionMove& extrusion_move : extrusion_moves | ranges::views::drop_last (1 ))
705+ {
706+ if (vSize2 (extrusion_move.position - current_position) >= MINIMUM_SQUARED_LINE_LENGTH)
707+ {
708+ extrusion_moves_filtered.push_back (extrusion_move);
709+ }
710+
711+ current_position = extrusion_move.position ;
712+ }
713+
714+ if (extrusion_moves_filtered.empty () || vSize2 (extrusion_moves.back ().position - current_position) >= MINIMUM_SQUARED_LINE_LENGTH)
715+ {
716+ extrusion_moves_filtered.push_back (extrusion_moves.back ());
717+ }
718+ else
719+ {
720+ extrusion_moves_filtered.back ().position = extrusion_moves.back ().position ;
721+ }
722+
723+ // Calculate max consecutive overhanging segment length
724+ current_position = start;
725+ for (const SegmentExtrusionMove& extrusion_move : extrusion_moves_filtered)
726+ {
727+ const bool is_overhanging = extrusion_move.speed_region_index > 0 ;
728+ update_is_overhanging (extrusion_move.position , current_position, is_overhanging);
729+ current_position = extrusion_move.position ;
730+ }
731+
732+ // Merge consecutive sub-segments that in the end have the same speed
733+ std::vector<SegmentExtrusionMove> extrusion_moves_merged;
734+ extrusion_moves_merged.reserve (extrusion_moves_filtered.size ());
735+ extrusion_moves_merged.push_back (extrusion_moves_filtered.front ());
736+
737+ for (const SegmentExtrusionMove& extrusion_move : extrusion_moves_filtered | ranges::views::drop (1 ))
738+ {
739+ const Ratio previous_speed_factor = overhang_masks_[extrusion_moves_merged.back ().speed_region_index ].speed_ratio ;
740+ const Ratio next_speed_factor = overhang_masks_[extrusion_move.speed_region_index ].speed_ratio ;
741+
742+ if (next_speed_factor == previous_speed_factor)
743+ {
744+ extrusion_moves_merged.back ().position = extrusion_move.position ;
715745 }
746+ else
747+ {
748+ extrusion_moves_merged.push_back (extrusion_move);
749+ }
750+ }
751+
752+ // Finally, add extrusion moves
753+ for (const SegmentExtrusionMove& extrusion_move : extrusion_moves_merged)
754+ {
755+ add_extrusion_move (extrusion_move.position , extrusion_move.speed_region_index );
716756 }
717757}
718758
0 commit comments