FIX: top z distance inaccurate if it's too large

The top z gap should be split if it's too large.
Also we use same logic for both synced and independent support layer.

jira: STUDIO-7232
github: #4191
Change-Id: Idca792e8fa51a83c2a09441ecac64d40b91d6390
This commit is contained in:
Arthur 2024-07-02 18:41:29 +08:00 committed by Lane.Wei
parent 2af6c4f4f4
commit c262a7ea13
1 changed files with 66 additions and 62 deletions

View File

@ -3160,71 +3160,72 @@ void TreeSupport::smooth_nodes(std::vector<std::vector<SupportNode*>>& contact_n
std::vector<LayerHeightData> TreeSupport::plan_layer_heights(std::vector<std::vector<SupportNode *>> &contact_nodes)
{
const coordf_t max_layer_height = m_slicing_params.max_layer_height;
const coordf_t layer_height = m_object_config->layer_height.value;
coordf_t z_distance_top = m_slicing_params.gap_support_object;
// BBS: add extra distance if thick bridge is enabled
// Note: normal support uses print_z, but tree support uses integer layers, so we need to subtract layer_height
if (!m_slicing_params.soluble_interface && m_object_config->thick_bridges) {
z_distance_top += m_object->layers()[0]->regions()[0]->region().bridging_height_avg(*m_print_config) - layer_height;
}
const size_t support_roof_layers = m_object_config->support_interface_top_layers.value;
const int z_distance_top_layers = round_up_divide(scale_(z_distance_top), scale_(layer_height)) + 1;
std::vector<LayerHeightData> layer_heights(contact_nodes.size());
std::vector<int> bounds;
std::map<int, std::pair<coordf_t,coordf_t>> bounds; // layer_nr:(print_z, height)
if (layer_height == max_layer_height || !m_support_params.independent_layer_height) {
for (int layer_nr = 0; layer_nr < contact_nodes.size(); layer_nr++) {
layer_heights[layer_nr] = {m_object->get_layer(layer_nr)->print_z, m_object->get_layer(layer_nr)->height, layer_nr > 0 ? size_t(layer_nr - 1) : 0};
}
}
else {
bounds.push_back(0);
{
// Keep first layer still
layer_heights[0] = { m_object->get_layer(0)->print_z, m_object->get_layer(0)->height, 0 };
bounds[0] = { m_object->get_layer(0)->print_z, m_object->get_layer(0)->height};
// Collect top contact layers
for (int layer_nr = 1; layer_nr < contact_nodes.size(); layer_nr++) {
if (!contact_nodes[layer_nr].empty()) {
bounds.push_back(layer_nr);
layer_heights[layer_nr].print_z = contact_nodes[layer_nr].front()->print_z;
layer_heights[layer_nr].height = contact_nodes[layer_nr].front()->height;
BOOST_LOG_TRIVIAL(trace) << "plan_layer_heights0 print_z, height, layer_nr: " << layer_heights[layer_nr].print_z << " " << layer_heights[layer_nr].height << " "
<< layer_nr;
coordf_t print_z = contact_nodes[layer_nr].front()->print_z;
coordf_t height = contact_nodes[layer_nr].front()->height;
if(height>m_slicing_params.max_suport_layer_height){
// split this layer into multiple layers if the gap is too big
int num_layers=std::ceil(height/m_slicing_params.max_suport_layer_height);
coordf_t new_height= height/num_layers;
for(auto& node: contact_nodes[layer_nr]) {
node->height = new_height;
node->distance_to_top = -num_layers;
node->support_roof_layers_below+=num_layers-1;
}
}
std::set<int> s(bounds.begin(), bounds.end());
bounds.assign(s.begin(), s.end());
for (size_t idx_extreme = 1; idx_extreme < bounds.size(); idx_extreme++) {
int extr2_layer_nr = bounds[idx_extreme];
coordf_t extr2z = layer_heights[extr2_layer_nr].bottom_z();
int extr1_layer_nr = bounds[idx_extreme - 1];
coordf_t extr1z = layer_heights[extr1_layer_nr].print_z;
for (int i=0; i<num_layers; ++i) {
bounds[layer_nr-i]={print_z, new_height};
print_z-=new_height;
}
}else{
bounds[layer_nr]={print_z, height};
}
}
}
auto it1 = bounds.begin();
auto it2 = bounds.begin();
it2++;
for (; it2 != bounds.end();it1++, it2++) {
int extr2_layer_nr = it2->first;
coordf_t extr2z = it2->second.first - it2->second.second; // bottom_z of upper bound
int extr1_layer_nr = it1->first; //bounds[idx_extreme - 1];
coordf_t extr1z = it1->second.first;// print_z of lower bound
coordf_t dist = extr2z - extr1z;
layer_heights[extr2_layer_nr].print_z = it2->second.first;
layer_heights[extr2_layer_nr].height = it2->second.second;
BOOST_LOG_TRIVIAL(trace) << "plan_layer_heights0 print_z, height, layer_nr: " << layer_heights[extr2_layer_nr].print_z << " " << layer_heights[extr2_layer_nr].height << " " << extr2_layer_nr;
// Insert intermediate layers.
size_t n_layers_extra = size_t(ceil(dist / (m_slicing_params.max_suport_layer_height + EPSILON)));
int actual_internel_layers = extr2_layer_nr - extr1_layer_nr - 1;
int extr_layers_left = extr2_layer_nr - extr1_layer_nr - n_layers_extra - 1;
size_t n_layers_extra = m_support_params.independent_layer_height ? size_t(ceil(dist / (m_slicing_params.max_suport_layer_height))) :
size_t(ceil(dist / (m_slicing_params.min_layer_height)));
if (n_layers_extra < 1)
continue;
coordf_t step = dist / coordf_t(n_layers_extra);
coordf_t print_z = extr1z + step;
//assert(step >= layer_height - EPSILON);
coordf_t extr2z_large_steps = extr2z;
coordf_t print_z = extr1z;
for (int layer_nr = extr1_layer_nr + 1; layer_nr < extr2_layer_nr; layer_nr++) {
// if (curr_layer_nodes.empty()) continue;
if (std::abs(print_z - m_object->get_layer(layer_nr)->print_z) < step / 2 + EPSILON || extr_layers_left < 1) {
Layer* layer = m_object->get_layer(layer_nr);
if (!m_support_params.independent_layer_height) step = layer->height;
if (std::abs((print_z+step) - layer->print_z) < step / 2 + EPSILON) {
print_z += step;
layer_heights[layer_nr].print_z = print_z;
layer_heights[layer_nr].height = step;
print_z += step;
}
else {
// can't clear curr_layer_nodes, or the model will have empty layers
layer_heights[layer_nr].print_z = 0.0;
layer_heights[layer_nr].height = 0.0;
extr_layers_left--;
}
}
}
@ -3350,8 +3351,11 @@ void TreeSupport::generate_contact_points(std::vector<std::vector<SupportNode*>>
contact_node->is_sharp_tail = is_sharp_tail;
if (is_sharp_tail) {
int ind = overhang_part.contour.closest_point_index(pt);
auto n1 = (overhang_part.contour[ind] - overhang_part.contour[ind - 1]).cast<double>().normalized();
auto n2 = (overhang_part.contour[ind] - overhang_part.contour[ind + 1]).cast<double>().normalized();
int nSize = overhang_part.contour.points.size();
int ind_prev = (ind - 1 + nSize) % nSize;
int ind_next = (ind + 1) % nSize;
auto n1 = (overhang_part.contour[ind] - overhang_part.contour[ind_prev]).cast<double>().normalized();
auto n2 = (overhang_part.contour[ind] - overhang_part.contour[ind_next]).cast<double>().normalized();
contact_node->skin_direction = scaled((n1 + n2).normalized());
}
curr_nodes.emplace_back(contact_node);