mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-16 11:17:51 -06:00
ENH: improve the support of blade-shape overhangs
1. reduce the gap between blade-shape overhang and support github: #3667 2. improve sharp tail detection of blade-shape overhangs by introducing lslices_extrudable. github: #2786, #3367 jira: STUDIO-5065, STUDIO-6038 Change-Id: I4e899eace1aa28b100a6f4ce2b8d740c317f5530 (cherry picked from commit 08328b848e39c345b6c7b64021d1e0f04df24d08) (cherry picked from commit 22056d5f7e7bef5574b53fc0453781cd365bf0e1)
This commit is contained in:
parent
c199730004
commit
107551f7b4
3 changed files with 37 additions and 38 deletions
|
@ -139,7 +139,7 @@ public:
|
||||||
// BBS
|
// BBS
|
||||||
mutable ExPolygons sharp_tails;
|
mutable ExPolygons sharp_tails;
|
||||||
mutable ExPolygons cantilevers;
|
mutable ExPolygons cantilevers;
|
||||||
mutable std::map<const ExPolygon*, float> sharp_tails_height;
|
mutable std::vector<float> sharp_tails_height;
|
||||||
|
|
||||||
// Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry
|
// Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry
|
||||||
// (with possibly differing extruder ID and slicing parameters) and merged.
|
// (with possibly differing extruder ID and slicing parameters) and merged.
|
||||||
|
@ -150,6 +150,7 @@ public:
|
||||||
// These lslices are also used to detect overhangs and overlaps between successive layers, therefore it is important
|
// These lslices are also used to detect overhangs and overlaps between successive layers, therefore it is important
|
||||||
// that the 1st lslice is not compensated by the Elephant foot compensation algorithm.
|
// that the 1st lslice is not compensated by the Elephant foot compensation algorithm.
|
||||||
ExPolygons lslices;
|
ExPolygons lslices;
|
||||||
|
ExPolygons lslices_extrudable; // BBS: the extrudable part of lslices used for tree support
|
||||||
std::vector<BoundingBox> lslices_bboxes;
|
std::vector<BoundingBox> lslices_bboxes;
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
|
|
|
@ -1412,6 +1412,7 @@ static inline ExPolygons detect_overhangs(
|
||||||
const coordf_t max_bridge_length = scale_(object_config.max_bridge_length.value);
|
const coordf_t max_bridge_length = scale_(object_config.max_bridge_length.value);
|
||||||
const bool bridge_no_support = object_config.bridge_no_support.value;
|
const bool bridge_no_support = object_config.bridge_no_support.value;
|
||||||
const coordf_t xy_expansion = scale_(object_config.support_expansion.value);
|
const coordf_t xy_expansion = scale_(object_config.support_expansion.value);
|
||||||
|
float lower_layer_offset = 0;
|
||||||
|
|
||||||
if (layer_id == 0)
|
if (layer_id == 0)
|
||||||
{
|
{
|
||||||
|
@ -1424,7 +1425,7 @@ static inline ExPolygons detect_overhangs(
|
||||||
!(bbox_size.x() > length_thresh_well_supported && bbox_size.y() > length_thresh_well_supported))
|
!(bbox_size.x() > length_thresh_well_supported && bbox_size.y() > length_thresh_well_supported))
|
||||||
{
|
{
|
||||||
layer.sharp_tails.push_back(slice);
|
layer.sharp_tails.push_back(slice);
|
||||||
layer.sharp_tails_height.insert({ &slice, layer.height });
|
layer.sharp_tails_height.push_back(layer.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1444,7 +1445,6 @@ static inline ExPolygons detect_overhangs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float lower_layer_offset = 0;
|
|
||||||
for (LayerRegion *layerm : layer.regions()) {
|
for (LayerRegion *layerm : layer.regions()) {
|
||||||
// Extrusion width accounts for the roundings of the extrudates.
|
// Extrusion width accounts for the roundings of the extrudates.
|
||||||
// It is the maximum widh of the extrudate.
|
// It is the maximum widh of the extrudate.
|
||||||
|
@ -1506,7 +1506,7 @@ static inline ExPolygons detect_overhangs(
|
||||||
if (is_sharp_tail) {
|
if (is_sharp_tail) {
|
||||||
ExPolygons overhang = diff_ex({ expoly }, lower_layer_expolys);
|
ExPolygons overhang = diff_ex({ expoly }, lower_layer_expolys);
|
||||||
layer.sharp_tails.push_back(expoly);
|
layer.sharp_tails.push_back(expoly);
|
||||||
layer.sharp_tails_height.insert({ &expoly, accum_height });
|
layer.sharp_tails_height.push_back(accum_height);
|
||||||
overhang = offset_ex(overhang, 0.05 * fw);
|
overhang = offset_ex(overhang, 0.05 * fw);
|
||||||
polygons_append(diff_polygons, to_polygons(overhang));
|
polygons_append(diff_polygons, to_polygons(overhang));
|
||||||
}
|
}
|
||||||
|
@ -1546,7 +1546,7 @@ static inline ExPolygons detect_overhangs(
|
||||||
if (layer.lower_layer) {
|
if (layer.lower_layer) {
|
||||||
for (ExPolygon& poly : overhang_areas) {
|
for (ExPolygon& poly : overhang_areas) {
|
||||||
float fw = float(layer.regions().front()->flow(frExternalPerimeter).scaled_width());
|
float fw = float(layer.regions().front()->flow(frExternalPerimeter).scaled_width());
|
||||||
auto cluster_boundary_ex = intersection_ex(poly, offset_ex(layer.lower_layer->lslices, scale_(0.5)));
|
auto cluster_boundary_ex = intersection_ex(poly, offset_ex(layer.lower_layer->lslices, std::max(fw, lower_layer_offset) + scale_(0.1)));
|
||||||
Polygons cluster_boundary = to_polygons(cluster_boundary_ex);
|
Polygons cluster_boundary = to_polygons(cluster_boundary_ex);
|
||||||
if (cluster_boundary.empty()) continue;
|
if (cluster_boundary.empty()) continue;
|
||||||
double dist_max = 0;
|
double dist_max = 0;
|
||||||
|
@ -2216,9 +2216,9 @@ SupportGeneratorLayersPtr PrintObjectSupportMaterial::top_contact_layers(
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2.3 check whether sharp tail exceed the max height
|
// 2.3 check whether sharp tail exceed the max height
|
||||||
for (const auto& lower_sharp_tail_height : lower_layer_sharptails_height) {
|
for (size_t i = 0; i < lower_layer_sharptails_height.size();i++) {
|
||||||
if (lower_sharp_tail_height.first->overlaps(expoly)) {
|
if (lower_layer_sharptails[i].overlaps(expoly)) {
|
||||||
accum_height += lower_sharp_tail_height.second;
|
accum_height += lower_layer_sharptails_height[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2243,7 +2243,7 @@ SupportGeneratorLayersPtr PrintObjectSupportMaterial::top_contact_layers(
|
||||||
if (is_sharp_tail) {
|
if (is_sharp_tail) {
|
||||||
ExPolygons overhang = diff_ex({ expoly }, lower_layer->lslices);
|
ExPolygons overhang = diff_ex({ expoly }, lower_layer->lslices);
|
||||||
layer->sharp_tails.push_back(expoly);
|
layer->sharp_tails.push_back(expoly);
|
||||||
layer->sharp_tails_height.insert({ &expoly, accum_height });
|
layer->sharp_tails_height.push_back( accum_height );
|
||||||
append(overhangs_per_layers[layer_nr], overhang);
|
append(overhangs_per_layers[layer_nr], overhang);
|
||||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
SVG svg(get_svg_filename(std::to_string(layer->print_z), "sharp_tail"), object.bounding_box());
|
SVG svg(get_svg_filename(std::to_string(layer->print_z), "sharp_tail"), object.bounding_box());
|
||||||
|
|
|
@ -752,6 +752,17 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||||
max_cantilever_dist = 0;
|
max_cantilever_dist = 0;
|
||||||
m_highest_overhang_layer = 0;
|
m_highest_overhang_layer = 0;
|
||||||
|
|
||||||
|
// calc the extrudable expolygons of each layer
|
||||||
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, m_object->layer_count()),
|
||||||
|
[&](const tbb::blocked_range<size_t>& range) {
|
||||||
|
for (size_t layer_nr = range.begin(); layer_nr < range.end(); layer_nr++) {
|
||||||
|
if (m_object->print()->canceled())
|
||||||
|
break;
|
||||||
|
Layer* layer = m_object->get_layer(layer_nr);
|
||||||
|
// Filter out areas whose diameter that is smaller than extrusion_width, but we don't want to lose any details.
|
||||||
|
layer->lslices_extrudable = intersection_ex(layer->lslices, offset2_ex(layer->lslices, -extrusion_width_scaled / 2, extrusion_width_scaled));
|
||||||
|
}
|
||||||
|
});
|
||||||
// main part of overhang detection can be parallel
|
// main part of overhang detection can be parallel
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, m_object->layer_count()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, m_object->layer_count()),
|
||||||
[&](const tbb::blocked_range<size_t>& range) {
|
[&](const tbb::blocked_range<size_t>& range) {
|
||||||
|
@ -770,7 +781,7 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||||
if (!((bbox_size.x() > length_thresh_well_supported && bbox_size.y() > length_thresh_well_supported))
|
if (!((bbox_size.x() > length_thresh_well_supported && bbox_size.y() > length_thresh_well_supported))
|
||||||
&& g_config_support_sharp_tails) {
|
&& g_config_support_sharp_tails) {
|
||||||
layer->sharp_tails.push_back(slice);
|
layer->sharp_tails.push_back(slice);
|
||||||
layer->sharp_tails_height.insert({ &slice, layer->height });
|
layer->sharp_tails_height.push_back(layer->height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -780,21 +791,8 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||||
coordf_t lower_layer_offset = layer_nr < enforce_support_layers ? -0.15 * extrusion_width : (float)lower_layer->height / tan(threshold_rad);
|
coordf_t lower_layer_offset = layer_nr < enforce_support_layers ? -0.15 * extrusion_width : (float)lower_layer->height / tan(threshold_rad);
|
||||||
//lower_layer_offset = std::min(lower_layer_offset, extrusion_width);
|
//lower_layer_offset = std::min(lower_layer_offset, extrusion_width);
|
||||||
coordf_t support_offset_scaled = scale_(lower_layer_offset);
|
coordf_t support_offset_scaled = scale_(lower_layer_offset);
|
||||||
// Filter out areas whose diameter that is smaller than extrusion_width. Do not use offset2() for this purpose!
|
ExPolygons& curr_polys = layer->lslices_extrudable;
|
||||||
ExPolygons lower_polys;
|
ExPolygons& lower_polys = lower_layer->lslices_extrudable;
|
||||||
for (const ExPolygon& expoly : lower_layer->lslices) {
|
|
||||||
if (!offset_ex(expoly, -extrusion_width_scaled / 2).empty()) {
|
|
||||||
lower_polys.emplace_back(expoly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExPolygons curr_polys;
|
|
||||||
std::vector<const ExPolygon*> curr_poly_ptrs;
|
|
||||||
for (const ExPolygon& expoly : layer->lslices) {
|
|
||||||
if (!offset_ex(expoly, -extrusion_width_scaled / 2).empty()) {
|
|
||||||
curr_polys.emplace_back(expoly);
|
|
||||||
curr_poly_ptrs.emplace_back(&expoly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// normal overhang
|
// normal overhang
|
||||||
ExPolygons lower_layer_offseted = offset_ex(lower_polys, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
ExPolygons lower_layer_offseted = offset_ex(lower_polys, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||||
|
@ -803,24 +801,24 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||||
if (is_auto(stype) && g_config_support_sharp_tails)
|
if (is_auto(stype) && g_config_support_sharp_tails)
|
||||||
{
|
{
|
||||||
// BBS detect sharp tail
|
// BBS detect sharp tail
|
||||||
for (const ExPolygon* expoly : curr_poly_ptrs) {
|
for (const ExPolygon& expoly : curr_polys) {
|
||||||
bool is_sharp_tail = false;
|
bool is_sharp_tail = false;
|
||||||
// 1. nothing below
|
// 1. nothing below
|
||||||
// this is a sharp tail region if it's floating and non-ignorable
|
// this is a sharp tail region if it's floating and non-ignorable
|
||||||
if (!overlaps(offset_ex(*expoly, 0.5 * extrusion_width_scaled), lower_polys)) {
|
if (!overlaps(offset_ex(expoly, 0.5 * extrusion_width_scaled), lower_polys)) {
|
||||||
is_sharp_tail = !offset_ex(*expoly, -0.1 * extrusion_width_scaled).empty();
|
is_sharp_tail = !offset_ex(expoly, -0.1 * extrusion_width_scaled).empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_sharp_tail) {
|
if (is_sharp_tail) {
|
||||||
ExPolygons overhang = diff_ex({ *expoly }, lower_polys);
|
ExPolygons overhang = diff_ex({ expoly }, lower_polys);
|
||||||
layer->sharp_tails.push_back(*expoly);
|
layer->sharp_tails.push_back(expoly);
|
||||||
layer->sharp_tails_height.insert({ expoly, layer->height });
|
layer->sharp_tails_height.push_back(layer->height);
|
||||||
append(overhang_areas, overhang);
|
append(overhang_areas, overhang);
|
||||||
|
|
||||||
if (!overhang.empty()) {
|
if (!overhang.empty()) {
|
||||||
has_sharp_tails = true;
|
has_sharp_tails = true;
|
||||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
SVG::export_expolygons(debug_out_path("sharp_tail_orig_%.02f.svg", layer->print_z), { expoly });
|
SVG::export_expolygons(debug_out_path("sharp_tail_orig_%.02f.svg", layer->print_z), { expoly });
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -834,7 +832,7 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||||
// check cantilever
|
// check cantilever
|
||||||
{
|
{
|
||||||
// lower_layer_offset may be very small, so we need to do max and then add 0.1
|
// lower_layer_offset may be very small, so we need to do max and then add 0.1
|
||||||
auto cluster_boundary_ex = intersection_ex(poly, offset_ex(lower_layer->lslices, scale_(std::max(extrusion_width,lower_layer_offset)+0.1)));
|
auto cluster_boundary_ex = intersection_ex(poly, offset_ex(lower_polys, scale_(std::max(extrusion_width,lower_layer_offset)+0.1)));
|
||||||
Polygons cluster_boundary = to_polygons(cluster_boundary_ex);
|
Polygons cluster_boundary = to_polygons(cluster_boundary_ex);
|
||||||
if (cluster_boundary.empty()) continue;
|
if (cluster_boundary.empty()) continue;
|
||||||
double dist_max = 0;
|
double dist_max = 0;
|
||||||
|
@ -877,7 +875,7 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||||
// BBS detect sharp tail
|
// BBS detect sharp tail
|
||||||
const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails;
|
const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails;
|
||||||
const auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height;
|
const auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height;
|
||||||
for (ExPolygon& expoly : layer->lslices) {
|
for (ExPolygon& expoly : layer->lslices_extrudable) {
|
||||||
bool is_sharp_tail = false;
|
bool is_sharp_tail = false;
|
||||||
float accum_height = layer->height;
|
float accum_height = layer->height;
|
||||||
do {
|
do {
|
||||||
|
@ -907,9 +905,9 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2.3 check whether sharp tail exceed the max height
|
// 2.3 check whether sharp tail exceed the max height
|
||||||
for (const auto& lower_sharp_tail_height : lower_layer_sharptails_height) {
|
for(size_t i=0;i<lower_layer_sharptails.size();i++) {
|
||||||
if (lower_sharp_tail_height.first->overlaps(expoly)) {
|
if (lower_layer_sharptails[i].overlaps(expoly)) {
|
||||||
accum_height += lower_sharp_tail_height.second;
|
accum_height += lower_layer_sharptails_height[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -933,7 +931,7 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||||
if (is_sharp_tail) {
|
if (is_sharp_tail) {
|
||||||
ExPolygons overhang = diff_ex({ expoly }, lower_layer->lslices);
|
ExPolygons overhang = diff_ex({ expoly }, lower_layer->lslices);
|
||||||
layer->sharp_tails.push_back(expoly);
|
layer->sharp_tails.push_back(expoly);
|
||||||
layer->sharp_tails_height.insert({ &expoly, accum_height });
|
layer->sharp_tails_height.push_back( accum_height);
|
||||||
append(ts_layer->overhang_areas, overhang);
|
append(ts_layer->overhang_areas, overhang);
|
||||||
|
|
||||||
if (!overhang.empty())
|
if (!overhang.empty())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue