mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-09 07:56:24 -06:00
ENH: improve sharp detection for small regions
1. improve sharp detection for small regions. When the region is around 1 extrsion width, previous method may miss some sharp tails. Now we reduce the width threshold to 0.1*extrusion_width for sharp tails. When checking "nothing below", need to expand the poly a little. Example: benchy. 2. improve is_support_necessary. Only popup warning for sharp tail and large cantilever (longer than 6mm). Jira: STUDIO-2567 Change-Id: I5e977e7766b35409891d1b41e36278e3f07fa372 (cherry picked from commit c9d8a7c1c3bbd4367c7fc44408c67e5c534167f4)
This commit is contained in:
parent
6ddcc14577
commit
0c2ba2b0a2
5 changed files with 28 additions and 22 deletions
|
@ -51,6 +51,7 @@ struct groupedVolumeSlices
|
||||||
enum SupportNecessaryType {
|
enum SupportNecessaryType {
|
||||||
NoNeedSupp=0,
|
NoNeedSupp=0,
|
||||||
SharpTail,
|
SharpTail,
|
||||||
|
Cantilever,
|
||||||
LargeOverhang,
|
LargeOverhang,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -458,7 +458,7 @@ void PrintObject::generate_support_material()
|
||||||
|
|
||||||
this->_generate_support_material();
|
this->_generate_support_material();
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
} else {
|
} else if(!m_print->get_no_check_flag()) {
|
||||||
// BBS: pop a warning if objects have significant amount of overhangs but support material is not enabled
|
// BBS: pop a warning if objects have significant amount of overhangs but support material is not enabled
|
||||||
m_print->set_status(50, L("Checking support necessity"));
|
m_print->set_status(50, L("Checking support necessity"));
|
||||||
typedef std::chrono::high_resolution_clock clock_;
|
typedef std::chrono::high_resolution_clock clock_;
|
||||||
|
@ -468,20 +468,16 @@ void PrintObject::generate_support_material()
|
||||||
SupportNecessaryType sntype = this->is_support_necessary();
|
SupportNecessaryType sntype = this->is_support_necessary();
|
||||||
|
|
||||||
double duration{ std::chrono::duration_cast<second_>(clock_::now() - t0).count() };
|
double duration{ std::chrono::duration_cast<second_>(clock_::now() - t0).count() };
|
||||||
BOOST_LOG_TRIVIAL(info) << std::fixed << std::setprecision(0)
|
BOOST_LOG_TRIVIAL(info) << std::fixed << std::setprecision(0) << "is_support_necessary takes " << duration << " secs.";
|
||||||
<< "is_support_necessary took " << (duration / 60) << " minutes and "
|
|
||||||
<< std::setprecision(3)
|
|
||||||
<< std::fmod(duration, 60.0) << " seconds." << std::endl;
|
|
||||||
|
|
||||||
if (sntype != NoNeedSupp) {
|
if (sntype != NoNeedSupp) {
|
||||||
if (sntype == SharpTail) {
|
std::map<SupportNecessaryType, std::string> reasons = {
|
||||||
std::string warning_message = format(L("It seems object %s has completely floating regions. Please re-orient the object or enable support generation."),
|
{SharpTail,L("floating regions")},
|
||||||
this->model_object()->name);
|
{Cantilever,L("floating cantilever")},
|
||||||
|
{LargeOverhang,L("large overhangs")} };
|
||||||
|
std::string warning_message = format(L("It seems object %s has %s. Please re-orient the object or enable support generation."),
|
||||||
|
this->model_object()->name, reasons[sntype]);
|
||||||
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, warning_message, PrintStateBase::SlicingNeedSupportOn);
|
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, warning_message, PrintStateBase::SlicingNeedSupportOn);
|
||||||
} else {
|
|
||||||
std::string warning_message = format(L("It seems object %s has large overhangs. Please enable support generation."), this->model_object()->name);
|
|
||||||
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, warning_message, PrintStateBase::SlicingNeedSupportOn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -2580,9 +2576,9 @@ template void PrintObject::remove_bridges_from_contacts<Polygons>(
|
||||||
|
|
||||||
SupportNecessaryType PrintObject::is_support_necessary()
|
SupportNecessaryType PrintObject::is_support_necessary()
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
static const double super_overhang_area_threshold = SQ(scale_(5.0));
|
static const double super_overhang_area_threshold = SQ(scale_(5.0));
|
||||||
|
const double cantilevel_dist_thresh = scale_(6);
|
||||||
|
#if 0
|
||||||
double threshold_rad = (m_config.support_threshold_angle.value < EPSILON ? 30 : m_config.support_threshold_angle.value + 1) * M_PI / 180.;
|
double threshold_rad = (m_config.support_threshold_angle.value < EPSILON ? 30 : m_config.support_threshold_angle.value + 1) * M_PI / 180.;
|
||||||
int enforce_support_layers = m_config.enforce_support_layers;
|
int enforce_support_layers = m_config.enforce_support_layers;
|
||||||
const coordf_t extrusion_width = m_config.line_width.value;
|
const coordf_t extrusion_width = m_config.line_width.value;
|
||||||
|
@ -2670,8 +2666,8 @@ SupportNecessaryType PrintObject::is_support_necessary()
|
||||||
this->clear_support_layers();
|
this->clear_support_layers();
|
||||||
if (tree_support.has_sharp_tails)
|
if (tree_support.has_sharp_tails)
|
||||||
return SharpTail;
|
return SharpTail;
|
||||||
else if (tree_support.has_cantilever)
|
else if (tree_support.has_cantilever && tree_support.max_cantilevel_dist > cantilevel_dist_thresh)
|
||||||
return LargeOverhang;
|
return Cantilever;
|
||||||
#endif
|
#endif
|
||||||
return NoNeedSupp;
|
return NoNeedSupp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1638,8 +1638,8 @@ static inline ExPolygons detect_overhangs(
|
||||||
// 1. nothing below
|
// 1. nothing below
|
||||||
// Check whether this is a sharp tail region.
|
// 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.
|
// 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({ expoly }, lower_layer_expolys)) {
|
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.5*fw).empty();
|
is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly,-0.1*fw).empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_sharp_tail) {
|
if (is_sharp_tail) {
|
||||||
|
@ -2366,6 +2366,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
if (layer->lower_layer == NULL) continue;
|
if (layer->lower_layer == NULL) continue;
|
||||||
Layer* lower_layer = layer->lower_layer;
|
Layer* lower_layer = layer->lower_layer;
|
||||||
auto cluster_boundary = intersection(cluster.merged_overhangs_dilated, offset(lower_layer->lslices, scale_(0.5)));
|
auto cluster_boundary = intersection(cluster.merged_overhangs_dilated, offset(lower_layer->lslices, scale_(0.5)));
|
||||||
|
if (cluster_boundary.empty()) continue;
|
||||||
double dist_max = 0;
|
double dist_max = 0;
|
||||||
Points cluster_pts;
|
Points cluster_pts;
|
||||||
for (auto& poly : cluster.merged_overhangs_dilated)
|
for (auto& poly : cluster.merged_overhangs_dilated)
|
||||||
|
|
|
@ -898,8 +898,8 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
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 small but non-ignorable
|
// this is a sharp tail region if it's small but non-ignorable
|
||||||
if (!overlaps({ expoly }, lower_polys)) {
|
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.5 * extrusion_width_scaled).empty();
|
is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly, -0.1 * extrusion_width_scaled).empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_sharp_tail) {
|
if (is_sharp_tail) {
|
||||||
|
@ -912,7 +912,10 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
has_sharp_tails = true;
|
has_sharp_tails = true;
|
||||||
#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"), m_object->bounding_box());
|
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");
|
if (svg.is_opened()) {
|
||||||
|
svg.draw(overhang, "yellow");
|
||||||
|
svg.draw(lower_layer->lslices, "red");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1045,11 +1048,13 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
m_object->project_and_append_custom_facets(false, EnforcerBlockerType::BLOCKER, blockers);
|
m_object->project_and_append_custom_facets(false, EnforcerBlockerType::BLOCKER, blockers);
|
||||||
|
|
||||||
// check whether the overhang cluster is cantilever (far awary from main body)
|
// check whether the overhang cluster is cantilever (far awary from main body)
|
||||||
|
max_cantilevel_dist = 0;
|
||||||
for (auto& cluster : overhangClusters) {
|
for (auto& cluster : overhangClusters) {
|
||||||
Layer* layer = m_object->get_layer(cluster.min_layer);
|
Layer* layer = m_object->get_layer(cluster.min_layer);
|
||||||
if (layer->lower_layer == NULL) continue;
|
if (layer->lower_layer == NULL) continue;
|
||||||
Layer* lower_layer = layer->lower_layer;
|
Layer* lower_layer = layer->lower_layer;
|
||||||
auto cluster_boundary = intersection(cluster.merged_poly, offset(lower_layer->lslices, scale_(0.5)));
|
auto cluster_boundary = intersection(cluster.merged_poly, offset(lower_layer->lslices, scale_(0.5)));
|
||||||
|
if (cluster_boundary.empty()) continue;
|
||||||
double dist_max = 0;
|
double dist_max = 0;
|
||||||
Points cluster_pts;
|
Points cluster_pts;
|
||||||
for (auto& poly : cluster.merged_poly)
|
for (auto& poly : cluster.merged_poly)
|
||||||
|
@ -1068,9 +1073,11 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
auto p_overhang = it->second;
|
auto p_overhang = it->second;
|
||||||
m_object->get_layer(layer_nr)->cantilevers.emplace_back(*p_overhang);
|
m_object->get_layer(layer_nr)->cantilevers.emplace_back(*p_overhang);
|
||||||
}
|
}
|
||||||
|
max_cantilevel_dist = std::max(max_cantilevel_dist, dist_max);
|
||||||
cluster.is_cantilever = true;
|
cluster.is_cantilever = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "max_cantilevel_dist=" << max_cantilevel_dist;
|
||||||
|
|
||||||
if (is_auto(stype) && g_config_remove_small_overhangs) {
|
if (is_auto(stype) && g_config_remove_small_overhangs) {
|
||||||
if (blockers.size() < m_object->layer_count())
|
if (blockers.size() < m_object->layer_count())
|
||||||
|
|
|
@ -380,6 +380,7 @@ public:
|
||||||
bool has_overhangs = false;
|
bool has_overhangs = false;
|
||||||
bool has_sharp_tails = false;
|
bool has_sharp_tails = false;
|
||||||
bool has_cantilever = false;
|
bool has_cantilever = false;
|
||||||
|
double max_cantilevel_dist = 0;
|
||||||
SupportType support_type;
|
SupportType support_type;
|
||||||
SupportMaterialStyle support_style;
|
SupportMaterialStyle support_style;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue