ENH: [tree support] use layer_nr_next for calculate_avoidance
Previously we used layer_nr-1 as the next support layer below layer_nr, which was not right when we used independent support layer heights. And this would make it difficult for the tree branche to avoid the object. Change-Id: Ic705fbd093e4bd555470646044380703ca259904 (cherry picked from commit 245e1cf4fd071b1f1fea4c5d616ff87432a76911)
This commit is contained in:
parent
de6ba75f40
commit
d16dee04af
|
@ -2528,7 +2528,8 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
return move_dist;
|
return move_dist;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::pair<coordf_t, coordf_t>> layer_heights = plan_layer_heights(contact_nodes);
|
m_ts_data->layer_heights = plan_layer_heights(contact_nodes);
|
||||||
|
std::vector<LayerHeightData> &layer_heights = m_ts_data->layer_heights;
|
||||||
if (layer_heights.empty()) return;
|
if (layer_heights.empty()) return;
|
||||||
|
|
||||||
std::unordered_set<Node*> to_free_node_set;
|
std::unordered_set<Node*> to_free_node_set;
|
||||||
|
@ -2548,9 +2549,10 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
for (Node *p_node : contact_nodes[layer_nr]) {
|
for (Node *p_node : contact_nodes[layer_nr]) {
|
||||||
layer_node_dist.emplace(p_node->dist_mm_to_top);
|
layer_node_dist.emplace(p_node->dist_mm_to_top);
|
||||||
}
|
}
|
||||||
if (layer_nr < m_highest_overhang_layer && layer_heights[layer_nr].second>0) {
|
size_t layer_nr_next = layer_heights[layer_nr].next_layer_nr;
|
||||||
for (auto node_dist : all_layer_node_dist[layer_nr + 1])
|
if (layer_nr < m_highest_overhang_layer && layer_heights[layer_nr].height>0) {
|
||||||
layer_node_dist.emplace(node_dist + layer_heights[layer_nr].second);
|
for (auto node_dist : all_layer_node_dist[layer_nr_next])
|
||||||
|
layer_node_dist.emplace(node_dist + layer_heights[layer_nr].height);
|
||||||
}
|
}
|
||||||
for (auto node_dist : layer_node_dist) {
|
for (auto node_dist : layer_node_dist) {
|
||||||
layer_radius.emplace(calc_branch_radius(branch_radius, node_dist, diameter_angle_scale_factor));
|
layer_radius.emplace(calc_branch_radius(branch_radius, node_dist, diameter_angle_scale_factor));
|
||||||
|
@ -2578,11 +2580,9 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
if (layer_contact_nodes.empty())
|
if (layer_contact_nodes.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int layer_nr_next = layer_nr - 1;
|
int layer_nr_next = layer_heights[layer_nr].next_layer_nr;
|
||||||
while (layer_nr_next>=0 && layer_heights[layer_nr_next].second < EPSILON)
|
coordf_t print_z_next = layer_heights[layer_nr_next].print_z;
|
||||||
layer_nr_next--;
|
coordf_t height_next = layer_heights[layer_nr_next].height;
|
||||||
coordf_t print_z_next = layer_heights[layer_nr_next].first;
|
|
||||||
coordf_t height_next = layer_heights[layer_nr_next].second;
|
|
||||||
|
|
||||||
std::deque<std::pair<size_t, Node*>> unsupported_branch_leaves; // All nodes that are leaves on this layer that would result in unsupported ('mid-air') branches.
|
std::deque<std::pair<size_t, Node*>> unsupported_branch_leaves; // All nodes that are leaves on this layer that would result in unsupported ('mid-air') branches.
|
||||||
const Layer* ts_layer = m_object->get_support_layer(layer_nr);
|
const Layer* ts_layer = m_object->get_support_layer(layer_nr);
|
||||||
|
@ -2757,7 +2757,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||||
|
|
||||||
const bool to_buildplate = !is_inside_ex(m_ts_data->get_avoidance(0, layer_nr_next), next_position);
|
const bool to_buildplate = !is_inside_ex(m_ts_data->get_avoidance(0, layer_nr_next), next_position);
|
||||||
Node * next_node = new Node(next_position, new_distance_to_top, node.skin_direction, new_support_roof_layers_below, to_buildplate, p_node,
|
Node * next_node = new Node(next_position, new_distance_to_top, node.skin_direction, new_support_roof_layers_below, to_buildplate, p_node,
|
||||||
layer_heights[layer_nr_next].first, layer_heights[layer_nr_next].second, new_dist_mm_to_top);
|
print_z_next, height_next, new_dist_mm_to_top);
|
||||||
next_node->movement = next_position - node.position;
|
next_node->movement = next_position - node.position;
|
||||||
get_max_move_dist(next_node);
|
get_max_move_dist(next_node);
|
||||||
next_node->is_merged = true;
|
next_node->is_merged = true;
|
||||||
|
@ -3192,7 +3192,7 @@ void TreeSupport::adjust_layer_heights(std::vector<std::vector<Node*>>& contact_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<coordf_t, coordf_t>> TreeSupport::plan_layer_heights(std::vector<std::vector<Node*>>& contact_nodes)
|
std::vector<LayerHeightData> TreeSupport::plan_layer_heights(std::vector<std::vector<Node *>> &contact_nodes)
|
||||||
{
|
{
|
||||||
const PrintObjectConfig& config = m_object->config();
|
const PrintObjectConfig& config = m_object->config();
|
||||||
const PrintConfig & print_config = m_object->print()->config();
|
const PrintConfig & print_config = m_object->print()->config();
|
||||||
|
@ -3206,21 +3206,19 @@ std::vector<std::pair<coordf_t, coordf_t>> TreeSupport::plan_layer_heights(std::
|
||||||
}
|
}
|
||||||
const size_t support_roof_layers = config.support_interface_top_layers.value;
|
const size_t support_roof_layers = config.support_interface_top_layers.value;
|
||||||
const int z_distance_top_layers = round_up_divide(scale_(z_distance_top), scale_(layer_height)) + 1;
|
const int z_distance_top_layers = round_up_divide(scale_(z_distance_top), scale_(layer_height)) + 1;
|
||||||
std::vector<std::pair<coordf_t, coordf_t>> layer_heights(contact_nodes.size(), std::pair<coordf_t, coordf_t>(0.0, 0.0));
|
std::vector<LayerHeightData> layer_heights(contact_nodes.size());
|
||||||
std::vector<int> bounds;
|
std::vector<int> bounds;
|
||||||
|
|
||||||
if (!USE_PLAN_LAYER_HEIGHTS || layer_height == max_layer_height || !print_config.independent_support_layer_height) {
|
if (!USE_PLAN_LAYER_HEIGHTS || layer_height == max_layer_height || !print_config.independent_support_layer_height) {
|
||||||
for (int layer_nr = 0; layer_nr < contact_nodes.size(); layer_nr++) {
|
for (int layer_nr = 0; layer_nr < contact_nodes.size(); layer_nr++) {
|
||||||
layer_heights[layer_nr].first = m_object->get_layer(layer_nr)->print_z;
|
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};
|
||||||
layer_heights[layer_nr].second = m_object->get_layer(layer_nr)->height;
|
|
||||||
}
|
}
|
||||||
return layer_heights;
|
return layer_heights;
|
||||||
}
|
}
|
||||||
|
|
||||||
bounds.push_back(0);
|
bounds.push_back(0);
|
||||||
// Keep first layer still
|
// Keep first layer still
|
||||||
layer_heights[0].first = m_object->get_layer(0)->print_z;
|
layer_heights[0] = {m_object->get_layer(0)->print_z, m_object->get_layer(0)->height, 0};
|
||||||
layer_heights[0].second = m_object->get_layer(0)->height;
|
|
||||||
// Collect top contact layers
|
// Collect top contact layers
|
||||||
for (int layer_nr = 1; layer_nr < contact_nodes.size(); layer_nr++)
|
for (int layer_nr = 1; layer_nr < contact_nodes.size(); layer_nr++)
|
||||||
{
|
{
|
||||||
|
@ -3228,8 +3226,8 @@ std::vector<std::pair<coordf_t, coordf_t>> TreeSupport::plan_layer_heights(std::
|
||||||
for (int i = 0; i < support_roof_layers + z_distance_top_layers + 1; i++) {
|
for (int i = 0; i < support_roof_layers + z_distance_top_layers + 1; i++) {
|
||||||
if (layer_nr - i > 0) {
|
if (layer_nr - i > 0) {
|
||||||
bounds.push_back(layer_nr - i);
|
bounds.push_back(layer_nr - i);
|
||||||
layer_heights[layer_nr - i].first = m_object->get_layer(layer_nr - i)->print_z;
|
layer_heights[layer_nr - i].print_z = m_object->get_layer(layer_nr - i)->print_z;
|
||||||
layer_heights[layer_nr - i].second = m_object->get_layer(layer_nr - i)->height;
|
layer_heights[layer_nr - i].height = m_object->get_layer(layer_nr - i)->height;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
break;
|
break;
|
||||||
|
@ -3260,19 +3258,29 @@ std::vector<std::pair<coordf_t, coordf_t>> TreeSupport::plan_layer_heights(std::
|
||||||
for (int layer_nr = extr1_layer_nr + 1; layer_nr < extr2_layer_nr; layer_nr++) {
|
for (int layer_nr = extr1_layer_nr + 1; layer_nr < extr2_layer_nr; layer_nr++) {
|
||||||
// if (curr_layer_nodes.empty()) continue;
|
// 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) {
|
if (std::abs(print_z - m_object->get_layer(layer_nr)->print_z) < step / 2 + EPSILON || extr_layers_left < 1) {
|
||||||
layer_heights[layer_nr].first = print_z;
|
layer_heights[layer_nr].print_z = print_z;
|
||||||
layer_heights[layer_nr].second = step;
|
layer_heights[layer_nr].height = step;
|
||||||
print_z += step;
|
print_z += step;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// can't clear curr_layer_nodes, or the model will have empty layers
|
// can't clear curr_layer_nodes, or the model will have empty layers
|
||||||
layer_heights[layer_nr].first = 0.0;
|
layer_heights[layer_nr].print_z = 0.0;
|
||||||
layer_heights[layer_nr].second = 0.0;
|
layer_heights[layer_nr].height = 0.0;
|
||||||
extr_layers_left--;
|
extr_layers_left--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = layer_heights.size() - 1; i >= 0; i--) {
|
||||||
|
if (layer_heights[i].height < EPSILON) continue;
|
||||||
|
for (int j = i - 1; j >= 0; j--) {
|
||||||
|
if (layer_heights[j].height > EPSILON) {
|
||||||
|
layer_heights[i].next_layer_nr = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
// check bounds
|
// check bounds
|
||||||
if (1)
|
if (1)
|
||||||
|
@ -3286,7 +3294,7 @@ std::vector<std::pair<coordf_t, coordf_t>> TreeSupport::plan_layer_heights(std::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
for (int i = 0; i < layer_heights.size(); i++) { BOOST_LOG_TRIVIAL(info) << "plan_layer_heights print_z, height: "<< layer_heights[i].first << " " << layer_heights[i].second << std::endl; }
|
for (int i = 0; i < layer_heights.size(); i++) { BOOST_LOG_TRIVIAL(info) << "plan_layer_heights print_z, height: "<< layer_heights[i].print_z << " " << layer_heights[i].height << std::endl; }
|
||||||
|
|
||||||
return layer_heights;
|
return layer_heights;
|
||||||
}
|
}
|
||||||
|
@ -3622,13 +3630,18 @@ const ExPolygons& TreeSupportData::calculate_avoidance(const RadiusLayerPair& ke
|
||||||
// if the layer at 2N below the current one but we won't exceed our limit unless there are N*N uncalculated layers
|
// if the layer at 2N below the current one but we won't exceed our limit unless there are N*N uncalculated layers
|
||||||
// below our current one.
|
// below our current one.
|
||||||
constexpr auto max_recursion_depth = 100;
|
constexpr auto max_recursion_depth = 100;
|
||||||
|
size_t layer_nr_next = layer_nr;
|
||||||
|
for (int i = 0; i < max_recursion_depth && layer_nr_next>0; i++) {
|
||||||
|
layer_nr_next = layer_heights[layer_nr_next].next_layer_nr;
|
||||||
|
}
|
||||||
// Check if we would exceed the recursion limit by trying to process this layer
|
// Check if we would exceed the recursion limit by trying to process this layer
|
||||||
if (layer_nr >= max_recursion_depth && m_avoidance_cache.find({radius, layer_nr - max_recursion_depth}) == m_avoidance_cache.end()) {
|
if (layer_nr >= max_recursion_depth && m_avoidance_cache.find({radius, layer_nr_next}) == m_avoidance_cache.end()) {
|
||||||
// Force the calculation of the layer `max_recursion_depth` below our current one, ignoring the result.
|
// Force the calculation of the layer `max_recursion_depth` below our current one, ignoring the result.
|
||||||
get_avoidance(radius, layer_nr - max_recursion_depth);
|
get_avoidance(radius, layer_nr_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygons avoidance_areas = std::move(offset_ex(get_avoidance(radius, layer_nr - 1), scale_(-m_max_move)));
|
layer_nr_next = layer_heights[layer_nr].next_layer_nr;
|
||||||
|
ExPolygons avoidance_areas = std::move(offset_ex(get_avoidance(radius, layer_nr_next), scale_(-m_max_move)));
|
||||||
const ExPolygons &collision = get_collision(radius, layer_nr);
|
const ExPolygons &collision = get_collision(radius, layer_nr);
|
||||||
avoidance_areas.insert(avoidance_areas.end(), collision.begin(), collision.end());
|
avoidance_areas.insert(avoidance_areas.end(), collision.begin(), collision.end());
|
||||||
avoidance_areas = std::move(union_ex(avoidance_areas));
|
avoidance_areas = std::move(union_ex(avoidance_areas));
|
||||||
|
|
|
@ -21,6 +21,15 @@ namespace Slic3r
|
||||||
class PrintObject;
|
class PrintObject;
|
||||||
class TreeSupport;
|
class TreeSupport;
|
||||||
|
|
||||||
|
struct LayerHeightData
|
||||||
|
{
|
||||||
|
coordf_t print_z = 0;
|
||||||
|
coordf_t height = 0;
|
||||||
|
size_t next_layer_nr = 0;
|
||||||
|
LayerHeightData() = default;
|
||||||
|
LayerHeightData(coordf_t z, coordf_t h, size_t next_layer) : print_z(z), height(h), next_layer_nr(next_layer) {}
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Lazily generates tree guidance volumes.
|
* \brief Lazily generates tree guidance volumes.
|
||||||
*
|
*
|
||||||
|
@ -79,6 +88,8 @@ public:
|
||||||
Polygons get_contours(size_t layer_nr) const;
|
Polygons get_contours(size_t layer_nr) const;
|
||||||
Polygons get_contours_with_holes(size_t layer_nr) const;
|
Polygons get_contours_with_holes(size_t layer_nr) const;
|
||||||
|
|
||||||
|
std::vector<LayerHeightData> layer_heights;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* \brief Convenience typedef for the keys to the caches
|
* \brief Convenience typedef for the keys to the caches
|
||||||
|
@ -423,7 +434,7 @@ private:
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::vector<std::pair<coordf_t, coordf_t>> plan_layer_heights(std::vector<std::vector<Node*>>& contact_nodes);
|
std::vector<LayerHeightData> plan_layer_heights(std::vector<std::vector<Node *>> &contact_nodes);
|
||||||
/*!
|
/*!
|
||||||
* \brief Creates points where support contacts the model.
|
* \brief Creates points where support contacts the model.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue