FIX: sharp tail detection misses some sharp tails

1. Previously if there are multiple sharp tails in a layer, some will be
 missed. To fix this, we should not skip if the current layer is already
 detected as sharp tails.
2. Do not mistakenly detect sharp horns as sharp tails by only detecting
 the overhang areas larger than half of the extrusion line width.

Github: #1578
Jira: STUDIO-2659
Change-Id: If7ba5c9ae547d3051551aa6fa34eb6214d01a46d
This commit is contained in:
Arthur 2023-05-11 17:45:33 +08:00 committed by Lane.Wei
parent 3d8383f127
commit 55a1141e67
2 changed files with 48 additions and 43 deletions

View File

@ -1634,25 +1634,28 @@ static inline ExPolygons detect_overhangs(
//FIXME add user defined filtering here based on minimal area or minimum radius or whatever.
// BBS
for (ExPolygon& expoly : layerm->raw_slices) {
bool is_sharp_tail = false;
float accum_height = layer.height;
if (g_config_support_sharp_tails) {
for (ExPolygon& expoly : layerm->raw_slices) {
if (offset_ex(expoly, -0.5 * fw).empty()) continue;
bool is_sharp_tail = false;
float accum_height = layer.height;
// 1. nothing below
// Check whether this is a sharp tail region.
// Should use lower_layer_expolys without any offset. Otherwise, it may missing sharp tails near the main body.
if (g_config_support_sharp_tails && !overlaps(offset_ex(expoly, 0.5 * fw), lower_layer_expolys)) {
is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly,-0.1*fw).empty();
}
// 1. nothing below
// Check whether this is a sharp tail region.
// Should use lower_layer_expolys without any offset. Otherwise, it may missing sharp tails near the main body.
if (!overlaps(offset_ex(expoly, 0.5 * fw), lower_layer_expolys)) {
is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly, -0.1 * fw).empty();
}
if (is_sharp_tail) {
ExPolygons overhang = diff_ex({ expoly }, lower_layer_polygons);
layer.sharp_tails.push_back(expoly);
layer.sharp_tails_height.insert({ &expoly, accum_height });
overhang = offset_ex(overhang, 0.05 * fw);
polygons_append(diff_polygons, to_polygons(overhang));
if (is_sharp_tail) {
ExPolygons overhang = diff_ex({ expoly }, lower_layer_expolys);
layer.sharp_tails.push_back(expoly);
layer.sharp_tails_height.insert({ &expoly, accum_height });
overhang = offset_ex(overhang, 0.05 * fw);
polygons_append(diff_polygons, to_polygons(overhang));
}
}
}
}
}
if (diff_polygons.empty())
@ -2269,15 +2272,12 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
const Layer* layer = object.get_layer(layer_nr);
const Layer* lower_layer = layer->lower_layer;
// skip if:
// 1) if the current layer is already detected as sharp tails
// 2) lower layer has no sharp tails
if (!lower_layer || layer->sharp_tails.empty() == false || lower_layer->sharp_tails.empty() == true)
if (!lower_layer)
continue;
// BBS detect sharp tail
const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails;
auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height;
const auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height;
for (const ExPolygon& expoly : layer->lslices) {
bool is_sharp_tail = false;
float accum_height = layer->height;
@ -2308,13 +2308,13 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
}
// 2.3 check whether sharp tail exceed the max height
for (auto& lower_sharp_tail_height : lower_layer_sharptails_height) {
for (const auto& lower_sharp_tail_height : lower_layer_sharptails_height) {
if (lower_sharp_tail_height.first->overlaps(expoly)) {
accum_height += lower_sharp_tail_height.second;
break;
}
}
if (accum_height >= sharp_tail_max_support_height) {
if (accum_height > sharp_tail_max_support_height) {
is_sharp_tail = false;
break;
}

View File

@ -864,9 +864,11 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
}
}
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);
}
}
@ -879,28 +881,30 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
overhang_areas.end());
ExPolygons overhangs_sharp_tail;
if (is_auto(stype) && g_config_support_sharp_tails)
{
// BBS detect sharp tail
const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails;
auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height;
for (ExPolygon& expoly : layer->lslices) {
for (const ExPolygon* expoly : curr_poly_ptrs) {
bool is_sharp_tail = false;
// 1. nothing below
// this is a sharp tail region if it's small but non-ignorable
if (!overlaps(offset_ex(expoly, 0.5 * extrusion_width_scaled), lower_polys)) {
is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly, -0.1 * extrusion_width_scaled).empty();
if (!overlaps(offset_ex(*expoly, 0.5 * extrusion_width_scaled), lower_polys)) {
is_sharp_tail = expoly->area() < area_thresh_well_supported && !offset_ex(*expoly, -0.1 * extrusion_width_scaled).empty();
}
if (is_sharp_tail) {
ExPolygons overhang = diff_ex({ expoly }, lower_layer->lslices);
layer->sharp_tails.push_back(expoly);
layer->sharp_tails_height.insert({ &expoly, layer->height });
ExPolygons overhang = diff_ex({ *expoly }, lower_polys);
layer->sharp_tails.push_back(*expoly);
layer->sharp_tails_height.insert({ expoly, layer->height });
append(overhang_areas, overhang);
if (!overhang.empty())
if (!overhang.empty()) {
has_sharp_tails = true;
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
SVG svg(format("SVG/sharp_tail_orig_%.02f.svg", layer->print_z), m_object->bounding_box());
if (svg.is_opened()) svg.draw(overhang, "red");
#endif
}
}
}
}
@ -947,15 +951,12 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
Layer* layer = m_object->get_layer(layer_nr);
SupportLayer* ts_layer = m_object->get_support_layer(layer_nr + m_raft_layers);
Layer* lower_layer = layer->lower_layer;
// skip if:
// 1) if the current layer is already detected as sharp tails
// 2) lower layer has no sharp tails
if (!lower_layer || layer->sharp_tails.empty() == false || lower_layer->sharp_tails.empty() == true)
if (!lower_layer)
continue;
// BBS detect sharp tail
const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails;
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) {
bool is_sharp_tail = false;
float accum_height = layer->height;
@ -986,13 +987,13 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
}
// 2.3 check whether sharp tail exceed the max height
for (auto& lower_sharp_tail_height : lower_layer_sharptails_height) {
for (const auto& lower_sharp_tail_height : lower_layer_sharptails_height) {
if (lower_sharp_tail_height.first->overlaps(expoly)) {
accum_height += lower_sharp_tail_height.second;
break;
}
}
if (accum_height >= sharp_tail_max_support_height) {
if (accum_height > sharp_tail_max_support_height) {
is_sharp_tail = false;
break;
}
@ -1018,8 +1019,8 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
if (!overhang.empty())
has_sharp_tails = true;
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
SVG svg(get_svg_filename(std::to_string(layer->print_z), "sharp_tail"), m_object->bounding_box());
if (svg.is_opened()) svg.draw(overhang, "yellow");
SVG svg(format("SVG/sharp_tail_%.02f.svg",layer->print_z), m_object->bounding_box());
if (svg.is_opened()) svg.draw(overhang, "red");
#endif
}
@ -1068,10 +1069,14 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
const Layer* layer1 = m_object->get_layer(cluster.min_layer);
BoundingBox bbox = cluster.merged_bbox;
bbox.merge(get_extents(layer1->lslices));
SVG svg(format("SVG/overhangCluster_%s_%s_tail=%s_cantilever=%s_small=%s.svg", cluster.min_layer, layer1->print_z, cluster.is_sharp_tail, cluster.is_cantilever, cluster.is_small_overhang), bbox);
SVG svg(format("SVG/overhangCluster_%s-%s_%s-%s_tail=%s_cantilever=%s_small=%s.svg",
cluster.min_layer, cluster.max_layer, layer1->print_z, m_object->get_layer(cluster.max_layer)->print_z,
cluster.is_sharp_tail, cluster.is_cantilever, cluster.is_small_overhang), bbox);
if (svg.is_opened()) {
svg.draw(layer1->lslices, "red");
svg.draw(cluster.merged_poly, "blue");
svg.draw_text(bbox.min + Point(scale_(0), scale_(2)), "lslices", "red", 2);
svg.draw_text(bbox.min + Point(scale_(0), scale_(2)), "overhang", "blue", 2);
}
#endif