ENH: remove duplicate height pair in layer height profiles

This is fix for jira-3493

Remove duplicated height pairs when add height range

Signed-off-by: salt.wei <salt.wei@bambulab.com>
Change-Id: If74c1f8af1c911d709b9582a15ea8852630c1a67
This commit is contained in:
salt.wei 2023-06-29 12:32:14 +08:00 committed by Lane.Wei
parent bed5fac0f8
commit 7910e681e4
1 changed files with 44 additions and 29 deletions

View File

@ -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<coordf_t> 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<std::pair<t_layer_height_range,coordf_t>> ranges_non_overlapping;
std::vector<std::pair<t_layer_height_range, coordf_t>> 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,coordf_t>(
t_layer_height_range(0., slicing_params.first_object_layer_height),
ranges_non_overlapping.push_back(std::pair<t_layer_height_range, coordf_t>(
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,coordf_t>(t_layer_height_range(lo, hi), height));
ranges_non_overlapping.push_back(std::pair<t_layer_height_range, coordf_t>(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<coordf_t> layer_height_profile;
for (std::vector<std::pair<t_layer_height_range,coordf_t>>::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<t_layer_height_range, coordf_t>& 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