From a4de5c6553678f7ccc631c1c74c129aae69e699a Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Tue, 24 Jan 2023 11:54:16 +0100 Subject: [PATCH] initial warnings version --- src/libslic3r/PrintObject.cpp | 138 +++++++++++++++++++++--- src/libslic3r/SupportSpotsGenerator.cpp | 7 ++ src/libslic3r/SupportSpotsGenerator.hpp | 7 +- 3 files changed, 134 insertions(+), 18 deletions(-) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 95e34bd05..f163bfbc8 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1,4 +1,5 @@ #include "Exception.hpp" +#include "Point.hpp" #include "Print.hpp" #include "BoundingBox.hpp" #include "ClipperUtils.hpp" @@ -21,9 +22,13 @@ #include "SupportSpotsGenerator.hpp" #include "TriangleSelectorWrapper.hpp" #include "format.hpp" +#include "libslic3r.h" +#include +#include #include #include +#include #include #include @@ -406,21 +411,6 @@ void PrintObject::ironing() } } - -/* -std::vector problematic_layers = SupportSpotsGenerator::quick_search(this); - if (!problematic_layers.empty()) { - std::cout << "Object needs supports" << std::endl; - this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, - L("Supportable issues found. Consider enabling supports for this object")); - this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, - L("Supportable issues found. Consider enabling supports for this object")); - for (size_t index = 0; index < std::min(problematic_layers.size(), size_t(4)); ++index) { - this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, - format(L("Layer with issues: %1%"), problematic_layers[index] + 1)); - } - } - */ void PrintObject::generate_support_spots() { if (this->set_started(posSupportSpotsSearch)) { @@ -434,6 +424,124 @@ void PrintObject::generate_support_spots() auto [supp_points, partial_objects] = SupportSpotsGenerator::full_search(this, cancel_func, params); this->m_shared_regions->generated_support_points = {this->trafo_centered(), supp_points}; m_print->throw_if_canceled(); + + auto check_problems = [&]() { + std::unordered_map sp_by_cause{}; + for (const SupportSpotsGenerator::SupportPoint &sp : supp_points) { + sp_by_cause[sp.cause].push_back(sp); + } + + if (!sp_by_cause[SupportSpotsGenerator::SupportPointCause::SeparationFromBed].empty()) { + this->active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL, + L("Object part may break from the bed. Consider adding brim and/or supports.")); + } + + std::reverse(partial_objects.begin(), partial_objects.end()); + std::sort(partial_objects.begin(), partial_objects.end(), + [](const SupportSpotsGenerator::PartialObject &left, const SupportSpotsGenerator::PartialObject &right) { + return left.volume > right.volume; + }); + + float max_volume_part = partial_objects.front().volume; + for (const SupportSpotsGenerator::PartialObject &p : partial_objects) { + if (p.volume > max_volume_part / 1000.0f && !p.connected_to_bed) { + this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, + L("Floating object parts detected. Please add supports.")); + return; + } + } + + if (!sp_by_cause[SupportSpotsGenerator::SupportPointCause::WeakObjectPart].empty()) { + this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, + L("Thin parts of the object may break. Please add supports.")); + return; + } + + if (!sp_by_cause[SupportSpotsGenerator::SupportPointCause::FloatingBridgeAnchor].empty()) { + Vec3f last_pos = Vec3f::Zero(); + size_t count = 0; + for (const SupportSpotsGenerator::SupportPoint &sp : + sp_by_cause[SupportSpotsGenerator::SupportPointCause::FloatingBridgeAnchor]) { + if ((sp.position - last_pos).squaredNorm() < 9.0f) { + count++; + last_pos = sp.position; + } else { + last_pos = sp.position; + count = 1; + } + if (count > 1) { + this->active_step_add_warning( + PrintStateBase::WarningLevel::CRITICAL, + L("Bridges without supported endpoints will collapse. Please add supports. ")); + break; + } + } + } + + if (!sp_by_cause[SupportSpotsGenerator::SupportPointCause::LongUnsupportedExtrusion].empty()) { + Vec3f last_pos = Vec3f::Zero(); + size_t count = 0; + for (const SupportSpotsGenerator::SupportPoint &sp : + sp_by_cause[SupportSpotsGenerator::SupportPointCause::LongUnsupportedExtrusion]) { + if ((sp.position - last_pos).squaredNorm() < 9.0f) { + count++; + last_pos = sp.position; + } else { + last_pos = sp.position; + count = 1; + } + if (count > 1) { + this->active_step_add_warning( + PrintStateBase::WarningLevel::CRITICAL, + L("Long unsupported extrusions will collapse. Please add supports. ")); + break; + } + } + } + + if (!sp_by_cause[SupportSpotsGenerator::SupportPointCause::LongBridge].empty()) { + this->active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL, + L("There are bridges longer than allowed distance. Consider adding supports. ")); + } + + if (!sp_by_cause[SupportSpotsGenerator::SupportPointCause::FloatingExtrusion].empty()) { + Vec3f last_pos = Vec3f::Zero(); + size_t count = 0; + bool small_warning = false; + for (const SupportSpotsGenerator::SupportPoint &sp : + sp_by_cause[SupportSpotsGenerator::SupportPointCause::FloatingExtrusion]) { + if ((sp.position - last_pos).squaredNorm() < + params.bridge_distance + EPSILON) { + count++; + last_pos = sp.position; + } else { + if (count > 6) { + this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, + L("Object has large part with loose extrusions. Please enable supports. ")); + small_warning = false; + break; + } + if (count > 3) { + small_warning = true; + } + + last_pos = sp.position; + count = 1; + } + } + if (small_warning) { + this->active_step_add_warning( + PrintStateBase::WarningLevel::NON_CRITICAL, + L("Object has parts with loose extrusions and may look bad. Consider enabling supports. ")); + } else if (sp_by_cause[SupportSpotsGenerator::SupportPointCause::FloatingExtrusion].size() > max_volume_part / 100) { + this->active_step_add_warning( + PrintStateBase::WarningLevel::NON_CRITICAL, + L("There are many loose surface extrusions on this object. Consider enabling supports. ")); + } + } + }; + + check_problems(); } BOOST_LOG_TRIVIAL(debug) << "Searching support spots - end"; this->set_done(posSupportSpotsSearch); diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index 0b0c1b457..464ee1d67 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -321,6 +321,12 @@ std::vector check_extrusion_entity_stability(const ExtrusionEntit curr_point.distance *= sign; SupportPointCause potential_cause = SupportPointCause::FloatingExtrusion; + if (curr_point.distance > flow_width * 5.0) { + if (std::abs(curr_point.curvature) > 0.1) + potential_cause = SupportPointCause::LongUnsupportedExtrusion; + else + potential_cause = SupportPointCause::LongBridge; + } float max_bridge_len = std::max(params.support_points_interface_radius * 2.0f, params.bridge_distance / @@ -919,6 +925,7 @@ void debug_export(const SupportPoints& support_points,const PartialObjects& obje case SupportPointCause::FloatingBridgeAnchor: color = {0.863281f, 0.109375f, 0.113281f}; break; //RED case SupportPointCause::LongBridge: color = {0.960938f, 0.90625f, 0.0625f}; break; // YELLOW case SupportPointCause::FloatingExtrusion: color = {0.921875f, 0.515625f, 0.101563f}; break; // ORANGE + case SupportPointCause::LongUnsupportedExtrusion: color = {0.863281f, 0.109375f, 0.113281f}; break; // RED case SupportPointCause::SeparationFromBed: color = {0.0f, 1.0f, 0.0}; break; // GREEN case SupportPointCause::UnstableFloatingPart: color = {0.105469f, 0.699219f, 0.84375f}; break; // BLUE case SupportPointCause::WeakObjectPart: color = {0.609375f, 0.210938f, 0.621094f}; break; // PURPLE diff --git a/src/libslic3r/SupportSpotsGenerator.hpp b/src/libslic3r/SupportSpotsGenerator.hpp index 98dda20e2..56762d544 100644 --- a/src/libslic3r/SupportSpotsGenerator.hpp +++ b/src/libslic3r/SupportSpotsGenerator.hpp @@ -32,8 +32,8 @@ struct Params // the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2] const float bridge_distance = 12.0f; // mm - const float max_acceleration; // mm/s^2 ; max acceleration of object (bed) in XY (NOTE: The max hit is received by the object in the - // jerk phase, so the usual machine limits are too low) + const float max_acceleration; // mm/s^2 ; max acceleration of object in XY -- should be applicable only to printers with bed slinger, + // however we do not have such info yet. The force is usually small anyway, so not such a big deal to include it everytime const int raft_layers_count; std::string filament_type; @@ -74,9 +74,10 @@ struct Params }; enum class SupportPointCause { - LongBridge, // point generated on bridge extrusion longer than the allowed length + LongBridge, // point generated on bridge and straight perimeter extrusion longer than the allowed length FloatingBridgeAnchor, // point generated on unsupported bridge endpoint FloatingExtrusion, // point generated on extrusion that does not hold on its own + LongUnsupportedExtrusion, // similar to above, but with large distance to object. This really needs supports. SeparationFromBed, // point generated for object parts that are connected to the bed, but the area is too small and there is a risk of separation (brim may help) UnstableFloatingPart, // point generated for object parts not connected to the bed, holded only by the other support points (brim will not help here) WeakObjectPart // point generated when some part of the object is too weak to hold the upper part and may break (imagine hourglass)