update libslic3r

This commit is contained in:
QIDI TECH
2025-08-04 10:13:51 +08:00
parent e3f49c2fb5
commit 8d4d60ec48
96 changed files with 4993 additions and 1903 deletions

View File

@@ -328,8 +328,8 @@ SupportGeneratorLayersPtr generate_raft_base(
}
// How much to inflate the support columns to be stable. This also applies to the 1st layer, if no raft layers are to be printed.
const float inflate_factor_fine = float(scale_((slicing_params.raft_layers() > 1) ? 0.5 : EPSILON));
const float inflate_factor_1st_layer = std::max(0.f, float(scale_(object.config().raft_first_layer_expansion)) - inflate_factor_fine);
const float inflate_factor_fine = float(scale_((slicing_params.raft_layers() > 1) ? 0.5 : EPSILON));
float inflate_factor_1st_layer = float(scale_(object.config().raft_first_layer_expansion));
SupportGeneratorLayer *contacts = top_contacts .empty() ? nullptr : top_contacts .front();
SupportGeneratorLayer *interfaces = interface_layers .empty() ? nullptr : interface_layers .front();
SupportGeneratorLayer *base_interfaces = base_interface_layers.empty() ? nullptr : base_interface_layers.front();
@@ -389,7 +389,11 @@ SupportGeneratorLayersPtr generate_raft_base(
new_layer.height = slicing_params.first_print_layer_height;
new_layer.bottom_z = 0.;
first_layer = union_(std::move(first_layer), base);
new_layer.polygons = inflate_factor_1st_layer > 0 ? expand(first_layer, inflate_factor_1st_layer) : first_layer;
if (inflate_factor_1st_layer < 0) { //means auto
inflate_factor_1st_layer = scale_(2.);
new_layer.polygons = expand(first_layer, inflate_factor_1st_layer - inflate_factor_fine);
} else
new_layer.polygons = inflate_factor_1st_layer > inflate_factor_fine ? expand(first_layer, inflate_factor_1st_layer - inflate_factor_fine) : first_layer;
}
// Insert the base layers.
for (size_t i = 1; i < slicing_params.base_raft_layers; ++ i) {
@@ -423,8 +427,17 @@ SupportGeneratorLayersPtr generate_raft_base(
//if (object.has_brim())
// trimming = offset(object.layers().front()->lslices, (float)scale_(object.config().brim_object_gap.value), SUPPORT_SURFACES_OFFSET_PARAMETERS);
//else
trimming = offset(object.layers().front()->lslices, (float)scale_(support_params.gap_xy_first_layer), SUPPORT_SURFACES_OFFSET_PARAMETERS);
if (inflate_factor_1st_layer > SCALED_EPSILON) {
trimming = offset(object.layers().front()->lslices, (float)scale_(support_params.gap_xy_first_layer), SUPPORT_SURFACES_OFFSET_PARAMETERS);
if (inflate_factor_1st_layer < 0) { //means auto
//for (const auto &expoly : to_expolygons(raft)) {
// //TODO: it's hard to get the exact support height here
// inflate_factor_1st_layer = std::max(0.,
// scale_(expoly.map_moment_to_expansion(max_speed, contacts_with_height.empty() ? 0 : contacts_with_height[0]->print_z)));
//}
inflate_factor_1st_layer = scale_(2.);
}
if (inflate_factor_1st_layer > inflate_factor_fine + SCALED_EPSILON) {
inflate_factor_1st_layer = inflate_factor_1st_layer - inflate_factor_fine;
// Inflate in multiple steps to avoid leaking of the support 1st layer through object walls.
auto nsteps = std::max(5, int(ceil(inflate_factor_1st_layer / support_params.first_layer_flow.scaled_width())));
float step = inflate_factor_1st_layer / nsteps;
@@ -1463,7 +1476,8 @@ void generate_support_toolpaths(
const SupportGeneratorLayersPtr &top_contacts,
const SupportGeneratorLayersPtr &intermediate_layers,
const SupportGeneratorLayersPtr &interface_layers,
const SupportGeneratorLayersPtr &base_interface_layers)
const SupportGeneratorLayersPtr &base_interface_layers,
const std::vector<ExPolygons> &cooldown_areas)
{
// loop_interface_processor with a given circle radius.
LoopInterfaceProcessor loop_interface_processor(1.5 * support_params.support_material_interface_flow.scaled_width());
@@ -1595,7 +1609,7 @@ void generate_support_toolpaths(
std::vector<LayerCache> layer_caches(support_layers.size());
tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, support_layers.size()),
[&config, &slicing_params, &support_params, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &base_interface_layers, &layer_caches, &loop_interface_processor,
[&config, &slicing_params, &support_params, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &base_interface_layers, &cooldown_areas, &layer_caches, &loop_interface_processor,
&bbox_object, &angles, &interface_angles, n_raft_layers, link_max_length_factor]
(const tbb::blocked_range<size_t>& range) {
// Indices of the 1st layer in their respective container at the support layer height.
@@ -1810,6 +1824,29 @@ void generate_support_toolpaths(
support_params, sheath, no_sort);
}
if (!cooldown_areas.empty() && !cooldown_areas[support_layer_id].empty()) {
std::function<void(ExtrusionEntitiesPtr &)> setOverhangDegreeImpl = [&](ExtrusionEntitiesPtr &entities) {
for (auto entityPtr : entities) {
if (overlaps(to_expolygons(entityPtr->polygons_covered_by_width()), cooldown_areas[support_layer_id])) {
if (ExtrusionEntityCollection *collection = dynamic_cast<ExtrusionEntityCollection *>(entityPtr)) {
setOverhangDegreeImpl(collection->entities);
} else if (ExtrusionPath *path = dynamic_cast<ExtrusionPath *>(entityPtr)) {
path->set_overhang_degree(10);
} else if (ExtrusionMultiPath *multipath = dynamic_cast<ExtrusionMultiPath *>(entityPtr)) {
for (ExtrusionPath &path : multipath->paths) { path.set_overhang_degree(10); }
} else if (ExtrusionLoop *loop = dynamic_cast<ExtrusionLoop *>(entityPtr)) {
for (ExtrusionPath &path : loop->paths) { path.set_overhang_degree(10); }
}
}
}
};
setOverhangDegreeImpl(base_layer.extrusions);
setOverhangDegreeImpl(top_contact_layer.extrusions);
setOverhangDegreeImpl(bottom_contact_layer.extrusions);
setOverhangDegreeImpl(interface_layer.extrusions);
setOverhangDegreeImpl(base_interface_layer.extrusions);
}
// Merge base_interface_layers to base_layers to avoid unneccessary retractions
if (! base_layer.empty() && ! base_interface_layer.empty() && ! base_layer.polygons_to_extrude().empty() && ! base_interface_layer.polygons_to_extrude().empty() &&
base_layer.could_merge(base_interface_layer))
@@ -1998,6 +2035,7 @@ sub clip_with_shape {
}
}
*/
/*!
* \brief Unions two Polygons. Ensures that if the input is non empty that the output also will be non empty.
* \param first[in] The first Polygon.

View File

@@ -72,7 +72,8 @@ void generate_support_toolpaths(
const SupportGeneratorLayersPtr &top_contacts,
const SupportGeneratorLayersPtr &intermediate_layers,
const SupportGeneratorLayersPtr &interface_layers,
const SupportGeneratorLayersPtr &base_interface_layers);
const SupportGeneratorLayersPtr &base_interface_layers,
const std::vector<ExPolygons> &cooldown_areas = {});
// FN_HIGHER_EQUAL: the provided object pointer has a Z value >= of an internal threshold.
// Find the first item with Z value >= of an internal threshold of fn_higher_equal.

View File

@@ -1775,7 +1775,7 @@ static inline std::pair<SupportGeneratorLayer*, SupportGeneratorLayer*> new_cont
// Contact layer will be printed with a normal flow, but
// it will support layers printed with a bridging flow.
if (object_config.thick_bridges && SupportMaterialInternal::has_bridging_extrusions(layer) && print_config.independent_support_layer_height) {
if (object_config.thick_bridges && SupportMaterialInternal::has_bridging_extrusions(layer)/* && print_config.independent_support_layer_height*/) {
coordf_t bridging_height = 0.;
for (const LayerRegion* region : layer.regions())
bridging_height += region->region().bridging_height_avg(print_config);
@@ -2928,7 +2928,7 @@ SupportGeneratorLayersPtr PrintObjectSupportMaterial::raft_and_intermediate_supp
for (size_t i = 0; i < top_contacts.size(); ++i)
assert(top_contacts[i]->height > 0.);
#endif /* _DEBUG */
return intermediate_layers;
}

View File

@@ -160,13 +160,13 @@ struct SupportParameters {
this->support_density > 0.95 || this->with_sheath ? ipRectilinear :
ipSupportBase;
this->interface_fill_pattern = (this->interface_density > 0.95 ? ipRectilinear : ipSupportBase);
this->raft_interface_fill_pattern = this->raft_interface_density > 0.95 ? ipRectilinear : ipSupportBase;
this->raft_interface_fill_pattern = this->raft_interface_density > 0.95 ? ipRectilinear : ipSupportBase;
if (object_config.support_interface_pattern == smipGrid)
this->contact_fill_pattern = ipGrid;
else if (object_config.support_interface_pattern == smipRectilinearInterlaced || object_config.support_interface_pattern == smipAuto)
this->contact_fill_pattern = ipRectilinear;
else
this->contact_fill_pattern = object_config.support_interface_pattern == smipConcentric ?
this->contact_fill_pattern = object_config.support_interface_pattern == smipConcentric ?
ipConcentric :
(this->interface_density > 0.95 ? ipRectilinear : ipSupportBase);
@@ -220,7 +220,7 @@ struct SupportParameters {
}
}
if(object_config.tree_support_wall_count.value==0){
if(object_config.tree_support_wall_count.value==-1){
tree_support_branch_diameter_double_wall = support_filament_strength;
this->tree_branch_diameter_double_wall_area_scaled = 0.25*sqr(scaled<double>(tree_support_branch_diameter_double_wall))*M_PI;
}else{
@@ -258,7 +258,7 @@ struct SupportParameters {
Flow support_material_flow;
Flow support_material_interface_flow;
Flow support_material_bottom_interface_flow;
// Flow at raft inteface & contact layers.
// Flow at raft inteface & contact layers.
Flow raft_interface_flow;
coordf_t support_extrusion_width;
// Is merging of regions allowed? Could the interface & base support regions be printed with the same extruder?

View File

@@ -945,7 +945,10 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
blocker = offset_ex(union_(blockers[layer_nr]), scale_(radius_sample_resolution));
if (!blocker.empty()) overhangs_all_layers[layer_nr] = diff_ex(overhangs_all_layers[layer_nr], blocker);
}
if (!enforced_overhangs.empty()) overhangs_all_layers[layer_nr] = union_ex(overhangs_all_layers[layer_nr], enforced_overhangs);
if (!enforced_overhangs.empty()) {
enforced_overhangs = diff_ex(offset_ex(enforced_overhangs, enforcer_overhang_offset), lower_layer->lslices_extrudable);
overhangs_all_layers[layer_nr] = union_ex(overhangs_all_layers[layer_nr], enforced_overhangs);
}
}
else if (layer_nr < enforcers.size() && lower_layer) {
if (!enforced_overhangs.empty()) {
@@ -1210,7 +1213,7 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
layer->loverhangs_with_type.clear();
for (const auto &cantilever : layer->cantilevers) add_overhang(layer, cantilever, OverhangType::Cantilever);
} else {
ExPolygons enforced_overhangs = to_expolygons(enforcers[layer_nr]);
ExPolygons enforced_overhangs = offset_ex(to_expolygons(enforcers[layer_nr]), enforcer_overhang_offset);
ExPolygons loverhangs_new;
std::vector<std::pair<ExPolygon, int>> loverhangs_with_type_new;
ExPolygons bigflat;
@@ -1507,7 +1510,7 @@ void TreeSupport::generate_toolpaths()
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
coordf_t nozzle_diameter = m_print_config->nozzle_diameter.get_at(object_config.support_filament - 1);
coordf_t layer_height = object_config.layer_height.value;
const size_t wall_count = object_config.tree_support_wall_count.value;
const int wall_count = object_config.tree_support_wall_count.value;
// coconut: use same intensity settings as SupportMaterial.cpp
auto m_support_material_interface_flow = support_material_interface_flow(m_object, float(m_slicing_params.layer_height));
@@ -1616,7 +1619,7 @@ void TreeSupport::generate_toolpaths()
filler_raft->angle = PI / 2;
filler_raft->spacing = support_flow.spacing();
for (auto& poly : first_non_raft_base)
make_perimeter_and_infill(ts_layer->support_fills.entities, poly, std::min(size_t(1), wall_count), support_flow, erSupportMaterial, filler_raft, interface_density, false);
make_perimeter_and_infill(ts_layer->support_fills.entities, poly, std::min(1, wall_count), support_flow, erSupportMaterial, filler_raft, interface_density, false);
}
if (m_object->support_layer_count() <= m_raft_layers)
@@ -1747,8 +1750,16 @@ void TreeSupport::generate_toolpaths()
filler_interface->layer_id = 0;
}
fill_expolygons_generate_paths(ts_layer->support_fills.entities, polys, filler_interface.get(), fill_params, erSupportMaterialInterface,
interface_flow);
ExtrusionEntityCollection *temp_support_fills = new ExtrusionEntityCollection();
for (auto &single_poly : union_ex(polys))
make_perimeter_and_infill(temp_support_fills->entities, single_poly, 1, interface_flow, erSupportMaterialInterface, filler_interface.get(),
interface_density, false);
temp_support_fills->no_sort = true; // make sure loops are first
if (!temp_support_fills->entities.empty())
ts_layer->support_fills.entities.push_back(temp_support_fills);
else
delete temp_support_fills;
}
else {
// base_areas
@@ -1773,17 +1784,35 @@ void TreeSupport::generate_toolpaths()
// allow infill-only mode if support is thick enough (so min_wall_count is 0);
// otherwise must draw 1 wall
// Don't need extra walls if we have infill. Extra walls may overlap with the infills.
size_t min_wall_count = 1;
make_perimeter_and_infill(ts_layer->support_fills.entities, poly, std::max(min_wall_count, wall_count), flow,
size_t min_wall_count = wall_count == 0 ? 0 : 1;
make_perimeter_and_infill(ts_layer->support_fills.entities, poly, std::max(int(min_wall_count), wall_count), flow,
erSupportMaterial, filler_support.get(), support_density);
}
else {
SupportParameters support_params = m_support_params;
if (area_group.need_extra_wall && object_config.tree_support_wall_count.value == 0)
if (area_group.need_extra_wall && object_config.tree_support_wall_count.value == -1)
support_params.tree_branch_diameter_double_wall_area_scaled = 0.1;
tree_supports_generate_paths(ts_layer->support_fills.entities, loops, flow, support_params);
}
}
if (area_group.need_cooling)
{
std::function<void(ExtrusionEntityCollection *)> setOverhangDegreeImpl = [&](ExtrusionEntityCollection *entity) {
for (auto entityPtr : entity->entities) {
if (ExtrusionEntityCollection *collection = dynamic_cast<ExtrusionEntityCollection *>(entityPtr)) {
setOverhangDegreeImpl(collection);
} else if (ExtrusionPath *path = dynamic_cast<ExtrusionPath *>(entityPtr)) {
path->set_overhang_degree(10);
} else if (ExtrusionMultiPath *multipath = dynamic_cast<ExtrusionMultiPath *>(entityPtr)) {
for (ExtrusionPath &path : multipath->paths) { path.set_overhang_degree(10); }
} else if (ExtrusionLoop *loop = dynamic_cast<ExtrusionLoop *>(entityPtr)) {
for (ExtrusionPath &path : loop->paths) { path.set_overhang_degree(10); }
}
}
};
setOverhangDegreeImpl(&ts_layer->support_fills);
}
}
}
if (m_support_params.base_fill_pattern == ipLightning)
@@ -2304,6 +2333,7 @@ void TreeSupport::draw_circles()
ts_layer->support_islands.reserve(curr_layer_nodes.size());
ExPolygons area_poly; // the polygon node area which will be printed as normal support
ExPolygons extra_wall_area; //where nodes would have extra walls
ExPolygons cooldown_area;
for (const SupportNode* p_node : curr_layer_nodes)
{
if (print->canceled())
@@ -2327,7 +2357,6 @@ void TreeSupport::draw_circles()
append(area_poly, area);
if (node.need_extra_wall) append(extra_wall_area, area);
}
if (tree_brim_width <= 0) brim_width = node.type == ePolygon ? 1 : 3;
}
else {
Polygon circle(branch_circle);
@@ -2352,15 +2381,16 @@ void TreeSupport::draw_circles()
circle.points[i] = circle.points[i] * scale + node.position;
}
}
brim_width = tree_brim_width > 0 ?
tree_brim_width :
std::max(MIN_BRANCH_RADIUS_FIRST_LAYER,
std::min(node.radius + node.dist_mm_to_top / (scale * branch_radius) * 0.5, MAX_BRANCH_RADIUS_FIRST_LAYER) - node.radius);
// brim_width = tree_brim_width > 0 ?
// tree_brim_width :
// std::max(MIN_BRANCH_RADIUS_FIRST_LAYER,
// std::min(node.radius + node.dist_mm_to_top / (scale * branch_radius) * 0.5, MAX_BRANCH_RADIUS_FIRST_LAYER) - node.radius);
area = avoid_object_remove_extra_small_parts(ExPolygon(circle), get_collision(node.is_sharp_tail && node.distance_to_top <= 0));
// area = diff_clipped({ ExPolygon(circle) }, get_collision(node.is_sharp_tail && node.distance_to_top <= 0));
if (!area.empty()) has_circle_node = true;
if (node.need_extra_wall) append(extra_wall_area, area);
if (node.overhang_degree >= 2) append(cooldown_area, area);
// merge overhang to get a smoother interface surface
// Do not merge when buildplate_only is on, because some underneath nodes may have been deleted.
@@ -2374,10 +2404,17 @@ void TreeSupport::draw_circles()
}
append(area, overhang_expanded);
}
}
if (layer_nr == 0 && m_raft_layers == 0)
if (layer_nr == 0 && m_raft_layers == 0) {
if (tree_brim_width >= 0) brim_width = tree_brim_width;
else {
for (const auto &expoly : area)
brim_width = std::max(brim_width, expoly.map_moment_to_expansion(m_object_config->support_speed.values[0], node.dist_mm_to_top));
}
area = safe_offset_inc(area, scale_(brim_width), get_collision(false), scale_(MIN_BRANCH_RADIUS * 0.5), 0, 1);
}
if (obj_layer_nr>0 && node.distance_to_top < 0)
append(roof_gap_areas, area);
else if (m_support_params.num_top_interface_layers > 0 && obj_layer_nr > 0 && (node.support_roof_layers_below == 0 || node.support_roof_layers_below == 1) &&
@@ -2461,6 +2498,7 @@ void TreeSupport::draw_circles()
area_groups.back().need_infill = overlaps({ expoly }, area_poly);
bool need_extra_wall = overlaps({expoly},extra_wall_area);
area_groups.back().need_extra_wall = need_extra_wall && !area_groups.back().need_infill;
area_groups.back().need_cooling = overlaps({ expoly }, cooldown_area);
}
for (auto& expoly : ts_layer->roof_areas) {
//if (area(expoly) < SQ(scale_(1))) continue;
@@ -2880,6 +2918,18 @@ void TreeSupport::drop_nodes()
if (!overlap_with_circle.empty() && is_inside_ex(overlap_with_circle, node.position)) {
continue;
}
Polygon circle = make_circle(scale_(node.radius), 0.00789 * scale_(node.radius));
circle.translate(node.position);
ExPolygons area = avoid_object_remove_extra_small_parts(ExPolygon(circle), get_collision(0, obj_layer_nr));
if (!area.empty()) {
p_node->overhang = area[0];
if (area[0].area() < SQ(scale_(1.)) || (!node.parent->to_buildplate && !overlaps({node.overhang}, {node.parent->overhang}))) {
p_node->valid = false;
p_node->is_processed = true;
continue;
}
} else
continue;
}
if (node.to_buildplate || parts.empty()) //It's outside, so make it go towards the build plate.
{
@@ -3362,8 +3412,10 @@ void TreeSupport::drop_nodes()
}
if (i_node->child) {
i_node->child->parent = i_node->parent;
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);
auto it = std::find(i_node->child->parents.begin(), i_node->child->parents.end(), i_node);
if (it != i_node->child->parents.end()) i_node->child->parents.erase(it);
if (!i_node->parents.empty())
append(i_node->child->parents, i_node->parents);
}
i_node->is_processed = true; // mark to be deleted later
@@ -3441,6 +3493,7 @@ void TreeSupport::smooth_nodes()
branch[i]->radius = radii1[i];
branch[i]->movement = (pts[i + 1] - pts[i - 1]) / 2;
branch[i]->is_processed = true;
branch[i]->overhang_degree = std::min(10.0, unscale_((branch[i]->movement).cast<double>().norm()) / m_object_config->support_line_width * 10);
if (branch[i]->parents.size() > 1 || (branch[i]->movement.x() > max_move || branch[i]->movement.y() > max_move) ||
(total_height > thresh_tall_branch && branch[i]->dist_mm_to_top < thresh_dist_to_top))
branch[i]->need_extra_wall = true;

View File

@@ -125,6 +125,7 @@ struct SupportNode
bool is_sharp_tail = false;
bool valid = true;
bool fading = false;
double overhang_degree = 0.0; // overhang degree for cooling just like perimeter
ExPolygon overhang; // when type==ePolygon, set this value to get original overhang area
coordf_t origin_area;
@@ -432,7 +433,6 @@ private:
SlicingParameters m_slicing_params;
// Various precomputed support parameters to be shared with external functions.
SupportParameters m_support_params;
//1.9.5
size_t m_raft_layers = 0; // number of raft layers, including raft base, raft interface, raft gap
size_t m_highest_overhang_layer = 0;
std::vector<std::vector<MinimumSpanningTree>> m_spanning_trees;

View File

@@ -4140,7 +4140,7 @@ static void generate_support_areas(Print &print, TreeSupport* tree_support, cons
// Outputs
layer_storage, top_contacts, interface_layers, base_interface_layers };
std::vector<ExPolygons> cooldown_areas(num_support_layers);
if (has_support) {
auto t_precalc = std::chrono::high_resolution_clock::now();
// value is the area where support may be placed. As this is calculated in CreateLayerPathing it is saved and reused in draw_areas
@@ -4185,7 +4185,7 @@ static void generate_support_areas(Print &print, TreeSupport* tree_support, cons
// this new function give correct result when raft is also enabled
organic_draw_branches(
*print.get_object(processing.second.front()), volumes, config, move_bounds,
bottom_contacts, top_contacts, interface_placer, intermediate_layers, layer_storage,
bottom_contacts, top_contacts, interface_placer, intermediate_layers, layer_storage, cooldown_areas,
throw_on_cancel);
#endif
@@ -4232,7 +4232,7 @@ static void generate_support_areas(Print &print, TreeSupport* tree_support, cons
// Don't fill in the tree supports, make them hollow with just a single sheath line.
print.set_status(69, _L("Generating support"));
generate_support_toolpaths(print_object.support_layers(), print_object.config(), support_params, print_object.slicing_parameters(),
raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers, base_interface_layers);
raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers, base_interface_layers, cooldown_areas);
auto t_end = std::chrono::high_resolution_clock::now();
BOOST_LOG_TRIVIAL(info) << "Total time of organic tree support: " << 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_end - t_start).count() << " ms";
@@ -4287,6 +4287,7 @@ void organic_draw_branches(
// Output:
SupportGeneratorLayersPtr& intermediate_layers,
SupportGeneratorLayerStorage& layer_storage,
std::vector<ExPolygons>& cooldown_areas,
std::function<void()> throw_on_cancel)
{
@@ -4336,6 +4337,30 @@ void organic_draw_branches(
organic_smooth_branches_avoid_collisions(print_object, volumes, config, elements_with_link_down, linear_data_layers, throw_on_cancel);
//save the cooling area
for (LayerIndex layer_idx = 0; layer_idx + 1 < LayerIndex(move_bounds.size()); ++layer_idx) {
auto &layer_elements = move_bounds[layer_idx];
for (auto &elem : layer_elements) {
if (!elem.parents.empty()) {
SupportElements *layer_above = layer_idx + 1 < LayerIndex(move_bounds.size()) ? &move_bounds[layer_idx + 1] : nullptr;
if (!layer_above) break;
for (auto &parent_elem : elem.parents) {
auto &parent = (*layer_above)[parent_elem];
double overhang_degree = std::min(10.0, (parent.state.result_on_layer - elem.state.result_on_layer).cast<double>().norm() /
config.support_line_width * 10);
if (overhang_degree >= 2) {
coord_t radius = support_element_radius(config, parent);
Polygon circle = make_circle(radius, radius / 100);
circle.translate(parent.state.result_on_layer);
cooldown_areas[layer_idx + 1].emplace_back(ExPolygon(circle));
}
}
}
}
}
// Reduce memory footprint. After this point only finalize_interface_and_support_areas() will use volumes and from that only collisions with zero radius will be used.
volumes.clear_all_but_object_collision();

View File

@@ -318,6 +318,7 @@ void organic_draw_branches(
// Output:
SupportGeneratorLayersPtr& intermediate_layers,
SupportGeneratorLayerStorage& layer_storage,
std::vector<ExPolygons>& cooldown_areas,
std::function<void()> throw_on_cancel);