1212#include < optional>
1313#include < unordered_set>
1414
15+ #include < range/v3/view/chunk_by.hpp>
1516#include < range/v3/view/concat.hpp>
1617#include < spdlog/spdlog.h>
1718
@@ -3089,8 +3090,13 @@ bool FffGcodeWriter::processInsets(
30893090 // the supported region is made up of those areas that really are supported by either model or support on the layer below
30903091 // expanded to take into account the overhang angle, the greater the overhang angle, the larger the supported area is
30913092 // considered to be
3092- const coord_t overhang_width = layer_height * std::tan (AngleRadians (overhang_angle));
3093- return fully_supported_region.offset (overhang_width + 10 );
3093+ if (overhang_angle < 90.0 )
3094+ {
3095+ const coord_t overhang_width = layer_height * std::tan (AngleRadians (overhang_angle));
3096+ return fully_supported_region.offset (overhang_width + 10 );
3097+ }
3098+
3099+ return Shape ();
30943100 };
30953101
30963102 // Build supported regions for all the overhang speeds. For a visual explanation of the result, see doc/gradual_overhang_speed.svg
@@ -3100,17 +3106,46 @@ bool FffGcodeWriter::processInsets(
31003106 const auto wall_overhang_angle = mesh.settings .get <AngleDegrees>(" wall_overhang_angle" );
31013107 if (overhang_angles_count > 0 && wall_overhang_angle < 90.0 )
31023108 {
3109+ struct SpeedRegion
3110+ {
3111+ AngleDegrees overhang_angle;
3112+ Ratio speed_factor;
3113+ };
3114+
3115+ // Create raw speed regions
31033116 const AngleDegrees overhang_step = (90.0 - wall_overhang_angle) / static_cast <double >(overhang_angles_count);
3104- for (size_t angle_index = 0 ; angle_index < overhang_angles_count; ++angle_index)
3117+ std::vector<SpeedRegion> speed_regions;
3118+ speed_regions.reserve (overhang_angles_count + 1 );
3119+
3120+ speed_regions.push_back (SpeedRegion{ wall_overhang_angle, 1 .0_r }); // Initial internal region, always 100% speed factor
3121+
3122+ for (size_t angle_index = 1 ; angle_index < overhang_angles_count; ++angle_index)
31053123 {
31063124 const AngleDegrees actual_wall_overhang_angle = wall_overhang_angle + static_cast <double >(angle_index) * overhang_step;
3107- const Ratio speed_factor = angle_index == 0 ? 1 .0_r : overhang_speed_factors[angle_index - 1 ];
3125+ const Ratio speed_factor = overhang_speed_factors[angle_index - 1 ];
31083126
3109- overhang_masks .push_back (LayerPlan::OverhangMask{ get_supported_region ( actual_wall_overhang_angle) , speed_factor });
3127+ speed_regions .push_back (SpeedRegion{ actual_wall_overhang_angle, speed_factor });
31103128 }
31113129
3112- // Add an empty region, which actually means everything and should be ignored anyway
3113- overhang_masks.push_back (LayerPlan::OverhangMask{ Shape (), overhang_speed_factors.back () });
3130+ speed_regions.push_back (SpeedRegion{ 90.0 , overhang_speed_factors.back () }); // Final "everything else" speed region
3131+
3132+ // Now merge regions that have similar speed factors (saves calculations and avoid generating micro-segments)
3133+ auto merged_regions = speed_regions
3134+ | ranges::views::chunk_by (
3135+ [](const auto & region_a, const auto & region_b)
3136+ {
3137+ return region_a.speed_factor == region_b.speed_factor ;
3138+ });
3139+
3140+ // If finally necessary, add actual calculated speed regions
3141+ if (std::ranges::distance (merged_regions) > 1 )
3142+ {
3143+ for (const auto & regions : merged_regions)
3144+ {
3145+ const SpeedRegion& last_region = *std::ranges::prev (regions.end ());
3146+ overhang_masks.push_back (LayerPlan::OverhangMask{ get_supported_region (last_region.overhang_angle ), last_region.speed_factor });
3147+ }
3148+ }
31143149 }
31153150 gcode_layer.setOverhangMasks (overhang_masks);
31163151
0 commit comments