diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index 53f70a81d..f0e6db208 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -164,61 +164,76 @@ SlicingParameters SlicingParameters::create_from_config( // Convert layer_config_ranges to layer_height_profile. Both are referenced to z=0, meaning the raft layers are not accounted for // in the height profile and the printed object may be lifted by the raft thickness at the time of the G-code generation. std::vector layer_height_profile_from_ranges( - const SlicingParameters &slicing_params, - const t_layer_config_ranges &layer_config_ranges) + const SlicingParameters& slicing_params, + const t_layer_config_ranges& layer_config_ranges) { // 1) If there are any height ranges, trim one by the other to make them non-overlapping. Insert the 1st layer if fixed. - std::vector> ranges_non_overlapping; + std::vector> ranges_non_overlapping; ranges_non_overlapping.reserve(layer_config_ranges.size() * 4); if (slicing_params.first_object_layer_height_fixed()) - ranges_non_overlapping.push_back(std::pair( - t_layer_height_range(0., slicing_params.first_object_layer_height), + ranges_non_overlapping.push_back(std::pair( + t_layer_height_range(0., slicing_params.first_object_layer_height), slicing_params.first_object_layer_height)); // The height ranges are sorted lexicographically by low / high layer boundaries. - for (t_layer_config_ranges::const_iterator it_range = layer_config_ranges.begin(); it_range != layer_config_ranges.end(); ++ it_range) { + for (t_layer_config_ranges::const_iterator it_range = layer_config_ranges.begin(); it_range != layer_config_ranges.end(); ++it_range) { coordf_t lo = it_range->first.first; coordf_t hi = std::min(it_range->first.second, slicing_params.object_print_z_height()); coordf_t height = it_range->second.option("layer_height")->getFloat(); - if (! ranges_non_overlapping.empty()) + if (!ranges_non_overlapping.empty()) // Trim current low with the last high. lo = std::max(lo, ranges_non_overlapping.back().first.second); if (lo + EPSILON < hi) // Ignore too narrow ranges. - ranges_non_overlapping.push_back(std::pair(t_layer_height_range(lo, hi), height)); + ranges_non_overlapping.push_back(std::pair(t_layer_height_range(lo, hi), height)); } // 2) Convert the trimmed ranges to a height profile, fill in the undefined intervals between z=0 and z=slicing_params.object_print_z_max() // with slicing_params.layer_height std::vector layer_height_profile; - for (std::vector>::const_iterator it_range = ranges_non_overlapping.begin(); it_range != ranges_non_overlapping.end(); ++ it_range) { - coordf_t lo = it_range->first.first; - coordf_t hi = it_range->first.second; - coordf_t height = it_range->second; - coordf_t last_z = layer_height_profile.empty() ? 0. : layer_height_profile[layer_height_profile.size() - 2]; - if (lo > last_z + EPSILON) { + auto last_z = [&layer_height_profile]() { + return layer_height_profile.empty() ? 0. : *(layer_height_profile.end() - 2); + }; + auto lh_append = [&layer_height_profile](coordf_t z, coordf_t layer_height) { + if (!layer_height_profile.empty()) { + bool last_z_matches = is_approx(*(layer_height_profile.end() - 2), z); + bool last_h_matches = is_approx(layer_height_profile.back(), layer_height); + if (last_h_matches) { + if (last_z_matches) { + // Drop a duplicate. + return; + } + if (layer_height_profile.size() >= 4 && is_approx(*(layer_height_profile.end() - 3), layer_height)) { + // Third repetition of the same layer_height. Update z of the last entry. + *(layer_height_profile.end() - 2) = z; + return; + } + } + } + layer_height_profile.push_back(z); + layer_height_profile.push_back(layer_height); + }; + + for (const std::pair& non_overlapping_range : ranges_non_overlapping) { + coordf_t lo = non_overlapping_range.first.first; + coordf_t hi = non_overlapping_range.first.second; + coordf_t height = non_overlapping_range.second; + if (coordf_t z = last_z(); lo > z + EPSILON) { // Insert a step of normal layer height. - layer_height_profile.push_back(last_z); - layer_height_profile.push_back(slicing_params.layer_height); - layer_height_profile.push_back(lo); - layer_height_profile.push_back(slicing_params.layer_height); + lh_append(z, slicing_params.layer_height); + lh_append(lo, slicing_params.layer_height); } // Insert a step of the overriden layer height. - layer_height_profile.push_back(lo); - layer_height_profile.push_back(height); - layer_height_profile.push_back(hi); - layer_height_profile.push_back(height); + lh_append(lo, height); + lh_append(hi, height); } - coordf_t last_z = layer_height_profile.empty() ? 0. : layer_height_profile[layer_height_profile.size() - 2]; - if (last_z < slicing_params.object_print_z_height()) { + if (coordf_t z = last_z(); z < slicing_params.object_print_z_height()) { // Insert a step of normal layer height up to the object top. - layer_height_profile.push_back(last_z); - layer_height_profile.push_back(slicing_params.layer_height); - layer_height_profile.push_back(slicing_params.object_print_z_height()); - layer_height_profile.push_back(slicing_params.layer_height); + lh_append(z, slicing_params.layer_height); + lh_append(slicing_params.object_print_z_height(), slicing_params.layer_height); } - return layer_height_profile; + return layer_height_profile; } // Based on the work of @platsch