mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-25 07:34:03 -06:00
FIX: solve tree support crash
jira: STUDIO-8509 Change-Id: I8658538d7919136efbbf0d48cbf3d366e0621ded (cherry picked from commit d5b14e5c094fd68426f1be4d78734f7b86888eb2)
This commit is contained in:
parent
7a26dde977
commit
07c7e2f910
2 changed files with 34 additions and 48 deletions
|
@ -1947,7 +1947,7 @@ void TreeSupport::draw_circles()
|
||||||
return;
|
return;
|
||||||
BOOST_LOG_TRIVIAL(info) << "draw_circles for object: " << m_object->model_object()->name;
|
BOOST_LOG_TRIVIAL(info) << "draw_circles for object: " << m_object->model_object()->name;
|
||||||
|
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, contact_nodes.size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, m_ts_data->layer_heights.size()),
|
||||||
[&](const tbb::blocked_range<size_t>& range)
|
[&](const tbb::blocked_range<size_t>& range)
|
||||||
{
|
{
|
||||||
for (size_t layer_nr = range.begin(); layer_nr < range.end(); layer_nr++)
|
for (size_t layer_nr = range.begin(); layer_nr < range.end(); layer_nr++)
|
||||||
|
@ -2597,7 +2597,8 @@ void TreeSupport::drop_nodes()
|
||||||
// Remove all circle neighbours that are completely inside the polygon and merge them into this node.
|
// Remove all circle neighbours that are completely inside the polygon and merge them into this node.
|
||||||
for (const Point &neighbour : neighbours) {
|
for (const Point &neighbour : neighbours) {
|
||||||
SupportNode * neighbour_node = nodes_this_part[neighbour];
|
SupportNode * neighbour_node = nodes_this_part[neighbour];
|
||||||
if(neighbour_node->type==ePolygon) continue;
|
if (neighbour_node->valid == false) continue;
|
||||||
|
if (neighbour_node->type == ePolygon) continue;
|
||||||
coord_t neighbour_radius = scale_(neighbour_node->radius);
|
coord_t neighbour_radius = scale_(neighbour_node->radius);
|
||||||
Point pt_north = neighbour + Point(0, neighbour_radius), pt_south = neighbour - Point(0, neighbour_radius),
|
Point pt_north = neighbour + Point(0, neighbour_radius), pt_south = neighbour - Point(0, neighbour_radius),
|
||||||
pt_west = neighbour - Point(neighbour_radius, 0), pt_east = neighbour + Point(neighbour_radius, 0);
|
pt_west = neighbour - Point(neighbour_radius, 0), pt_east = neighbour + Point(neighbour_radius, 0);
|
||||||
|
@ -2871,8 +2872,6 @@ void TreeSupport::drop_nodes()
|
||||||
for (; i_node != nullptr; i_node = i_node->parent)
|
for (; i_node != nullptr; i_node = i_node->parent)
|
||||||
{
|
{
|
||||||
size_t i_layer = i_node->obj_layer_nr;
|
size_t i_layer = i_node->obj_layer_nr;
|
||||||
std::vector<SupportNode*>::iterator to_erase = std::find(contact_nodes[i_layer].begin(), contact_nodes[i_layer].end(), i_node);
|
|
||||||
if (to_erase != contact_nodes[i_layer].end())
|
|
||||||
{
|
{
|
||||||
// update the parent-child chain
|
// update the parent-child chain
|
||||||
if (i_node->parent) {
|
if (i_node->parent) {
|
||||||
|
@ -2887,18 +2886,23 @@ void TreeSupport::drop_nodes()
|
||||||
i_node->child->parents.erase(std::find(i_node->child->parents.begin(), i_node->child->parents.end(), i_node));
|
i_node->child->parents.erase(std::find(i_node->child->parents.begin(), i_node->child->parents.end(), i_node));
|
||||||
append(i_node->child->parents, i_node->parents);
|
append(i_node->child->parents, i_node->parents);
|
||||||
}
|
}
|
||||||
contact_nodes[i_layer].erase(to_erase);
|
i_node->is_processed = true; // mark to be deleted later
|
||||||
i_node->valid = false;
|
|
||||||
|
|
||||||
for (SupportNode* neighbour : i_node->merged_neighbours)
|
for (SupportNode* neighbour : i_node->merged_neighbours)
|
||||||
{
|
{
|
||||||
unsupported_branch_leaves.push_front({ i_layer, neighbour });
|
if (neighbour && !neighbour->is_processed)
|
||||||
|
unsupported_branch_leaves.push_front({ i_layer, neighbour });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (auto &layer_contact_nodes : contact_nodes) {
|
||||||
|
if (!layer_contact_nodes.empty())
|
||||||
|
layer_contact_nodes.erase(std::remove_if(layer_contact_nodes.begin(), layer_contact_nodes.end(), [](SupportNode *node) { return node->is_processed; }),
|
||||||
|
layer_contact_nodes.end());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "after m_avoidance_cache.size()=" << m_ts_data->m_avoidance_cache.size();
|
BOOST_LOG_TRIVIAL(debug) << "after m_avoidance_cache.size()=" << m_ts_data->m_avoidance_cache.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3419,32 +3423,20 @@ SupportNode* TreeSupportData::create_node(const Point position, const int distan
|
||||||
{
|
{
|
||||||
// this function may be called from multiple threads, need to lock
|
// this function may be called from multiple threads, need to lock
|
||||||
m_mutex.lock();
|
m_mutex.lock();
|
||||||
SupportNode* node = new SupportNode(position, distance_to_top, obj_layer_nr, support_roof_layers_below, to_buildplate, parent, print_z_, height_, dist_mm_to_top_, radius_);
|
std::unique_ptr<SupportNode> node = std::make_unique<SupportNode>(position, distance_to_top, obj_layer_nr, support_roof_layers_below, to_buildplate, parent, print_z_, height_, dist_mm_to_top_, radius_);
|
||||||
contact_nodes.emplace_back(node);
|
SupportNode* raw_ptr = node.get();
|
||||||
|
contact_nodes.emplace_back(std::move(node));
|
||||||
m_mutex.unlock();
|
m_mutex.unlock();
|
||||||
if (parent)
|
if (parent)
|
||||||
node->movement = position - parent->position;
|
raw_ptr->movement = position - parent->position;
|
||||||
return node;
|
return raw_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeSupportData::clear_nodes()
|
void TreeSupportData::clear_nodes()
|
||||||
{
|
{
|
||||||
for (auto node : contact_nodes) {
|
tbb::spin_mutex::scoped_lock guard(m_mutex);
|
||||||
delete node;
|
|
||||||
}
|
|
||||||
contact_nodes.clear();
|
contact_nodes.clear();
|
||||||
}
|
}
|
||||||
void TreeSupportData::remove_invalid_nodes()
|
|
||||||
{
|
|
||||||
for (auto it = contact_nodes.begin(); it != contact_nodes.end();) {
|
|
||||||
if ((*it)->valid==false) {
|
|
||||||
delete (*it);
|
|
||||||
it = contact_nodes.erase(it);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
coordf_t TreeSupportData::ceil_radius(coordf_t radius) const
|
coordf_t TreeSupportData::ceil_radius(coordf_t radius) const
|
||||||
{
|
{
|
||||||
|
@ -3473,27 +3465,22 @@ const ExPolygons& TreeSupportData::calculate_avoidance(const RadiusLayerPair& ke
|
||||||
{
|
{
|
||||||
const auto &radius = key.radius;
|
const auto &radius = key.radius;
|
||||||
const auto &layer_nr = key.layer_nr;
|
const auto &layer_nr = key.layer_nr;
|
||||||
if (layer_nr == 0) {
|
ExPolygons avoidance_areas;
|
||||||
// avoid ExPolygons:~ExPolygons() in multi-threading case, as it's not thread-safe and may
|
if (layer_nr > 0) {
|
||||||
// cause crash in some cases. See STUDIO-8313.
|
// Avoidance for a given layer depends on all layers beneath it so could have very deep recursion depths if
|
||||||
if (m_avoidance_cache.find(key) == m_avoidance_cache.end())
|
// called at high layer heights. We can limit the reqursion depth to N by checking if the layer N
|
||||||
m_avoidance_cache[key] = get_collision(radius, 0);
|
// below the current one exists and if not, forcing the calculation of that layer. This may cause another recursion
|
||||||
return m_avoidance_cache[key];
|
// 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.
|
||||||
|
constexpr auto max_recursion_depth = 100;
|
||||||
|
// 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()) {
|
||||||
|
// Force the calculation of the layer `max_recursion_depth` below our current one, ignoring the result.
|
||||||
|
get_avoidance(radius, layer_nr - max_recursion_depth);
|
||||||
|
}
|
||||||
|
|
||||||
// Avoidance for a given layer depends on all layers beneath it so could have very deep recursion depths if
|
avoidance_areas = offset_ex(get_avoidance(radius, layer_nr - 1), scale_(-m_max_move_distances[layer_nr-1]));
|
||||||
// called at high layer heights. We can limit the reqursion depth to N by checking if the layer N
|
|
||||||
// below the current one exists and if not, forcing the calculation of that layer. This may cause another recursion
|
|
||||||
// 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.
|
|
||||||
constexpr auto max_recursion_depth = 100;
|
|
||||||
// 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()) {
|
|
||||||
// Force the calculation of the layer `max_recursion_depth` below our current one, ignoring the result.
|
|
||||||
get_avoidance(radius, layer_nr - max_recursion_depth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygons avoidance_areas = offset_ex(get_avoidance(radius, layer_nr - 1), scale_(-m_max_move_distances[layer_nr-1]));
|
|
||||||
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));
|
||||||
|
|
|
@ -247,10 +247,9 @@ public:
|
||||||
SupportNode* create_node(const Point position, const int distance_to_top, const int obj_layer_nr, const int support_roof_layers_below, const bool to_buildplate, SupportNode* parent,
|
SupportNode* create_node(const Point position, const int distance_to_top, const int obj_layer_nr, const int support_roof_layers_below, const bool to_buildplate, SupportNode* parent,
|
||||||
coordf_t print_z_, coordf_t height_, coordf_t dist_mm_to_top_ = 0, coordf_t radius_ = 0);
|
coordf_t print_z_, coordf_t height_, coordf_t dist_mm_to_top_ = 0, coordf_t radius_ = 0);
|
||||||
void clear_nodes();
|
void clear_nodes();
|
||||||
void remove_invalid_nodes();
|
|
||||||
std::vector<LayerHeightData> layer_heights;
|
std::vector<LayerHeightData> layer_heights;
|
||||||
|
|
||||||
std::vector<SupportNode*> contact_nodes;
|
std::vector<std::unique_ptr<SupportNode>> contact_nodes;
|
||||||
// ExPolygon m_machine_border;
|
// ExPolygon m_machine_border;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue