From 5839e78a5e1e3f44e082591a6e6262956a2e7444 Mon Sep 17 00:00:00 2001
From: PavelMikus <pavel.mikus.mail@seznam.cz>
Date: Thu, 26 Jan 2023 13:18:29 +0100
Subject: [PATCH 1/3] minor issues fix

---
 src/libslic3r/PrintConfig.cpp           |  2 +-
 src/libslic3r/SupportSpotsGenerator.cpp | 50 +++++++++++++++----------
 2 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index 1d0446ce2..779261abd 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -537,7 +537,7 @@ void PrintConfigDef::init_fff_params()
     def->set_default_value(new ConfigOptionFloat(60));
 
     def             = this->add("enable_dynamic_overhang_speeds", coBool);
-    def->label      = L("Enable dynamic overhang speeds (Experimental)");
+    def->label      = L("Enable dynamic overhang speeds");
     def->category   = L("Speed");
     def->tooltip    = L("This setting enables dynamic speed control on overhangs.");
     def->mode       = comAdvanced;
diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp
index 3820aa4d5..9bf9dbdef 100644
--- a/src/libslic3r/SupportSpotsGenerator.cpp
+++ b/src/libslic3r/SupportSpotsGenerator.cpp
@@ -260,8 +260,8 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
 
             SupportPointCause potential_cause = std::abs(curr_point.curvature) > 0.1 ? SupportPointCause::FloatingBridgeAnchor :
                                                                                        SupportPointCause::LongBridge;
-            float         line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f;
-            Vec2d line_dir = (curr_point.position - prev_point.position).normalized();
+            float line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f;
+            Vec2d line_dir = line_len > EPSILON ? Vec2d((curr_point.position - prev_point.position) / double(line_len)) : Vec2d::Zero();
 
             ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast<float>() : curr_point.position.cast<float>(),
                                    curr_point.position.cast<float>(), line_len, entity};
@@ -335,14 +335,6 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
                 line_out.form_quality = 0.8f;
                 bridged_distance += line_len;
                 if (bridged_distance > max_bridge_len) {
-                    std::cout << "Problem found A: " << std::endl;
-                    std::cout << "bridged_distance: " << bridged_distance << std::endl;
-                    std::cout << "max_bridge_len: " << max_bridge_len << std::endl;
-                    std::cout << "line_out.form_quality: " << line_out.form_quality << std::endl;
-                    std::cout << "curr_point.distance: " << curr_point.distance << std::endl;
-                    std::cout << "curr_point.curvature: " << curr_point.curvature << std::endl;
-                    std::cout << "flow_width: " << flow_width << std::endl;
-
                     line_out.support_point_generated = potential_cause;
                     bridged_distance                 = 0.0f;
                 }
@@ -350,14 +342,6 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
                 bridged_distance += line_len;
                 line_out.form_quality = nearest_prev_layer_line.form_quality - 0.3f;
                 if (line_out.form_quality < 0 && bridged_distance > max_bridge_len) {
-                    std::cout << "Problem found B: " << std::endl;
-                    std::cout << "bridged_distance: " << bridged_distance << std::endl;
-                    std::cout << "max_bridge_len: " << max_bridge_len << std::endl;
-                    std::cout << "line_out.form_quality: " << line_out.form_quality << std::endl;
-                    std::cout << "curr_point.distance: " << curr_point.distance << std::endl;
-                    std::cout << "curr_point.curvature: " << curr_point.curvature << std::endl;
-                    std::cout << "flow_width: " << flow_width << std::endl;
-
                     line_out.support_point_generated = potential_cause;
                     line_out.form_quality            = 0.5f;
                     bridged_distance                 = 0.0f;
@@ -662,7 +646,8 @@ std::tuple<ObjectPart, float> build_object_part_from_slice(const size_t &slice_i
     }
 
     //  BRIM HANDLING
-    if (layer->id() == params.raft_layers_count && params.raft_layers_count == 0 && params.brim_type != BrimType::btNoBrim) {
+    if (layer->id() == params.raft_layers_count && params.raft_layers_count == 0 && params.brim_type != BrimType::btNoBrim &&
+        params.brim_width > 0.0) {
         // TODO: The algorithm here should take into account that multiple slices may have coliding Brim areas and the final brim area is
         // smaller,
         //  thus has lower adhesion. For now this effect will be neglected.
@@ -921,7 +906,8 @@ std::tuple<SupportPoints, PartialObjects> check_stability(const PrintObject *po,
                 for (const auto &perimeter_idx : island.perimeters) {
                     const ExtrusionEntity     *entity = perimeter_region->perimeters().entities[perimeter_idx];
                     std::vector<ExtrusionLine> perims = check_extrusion_entity_stability(entity, perimeter_region,
-                                                                                         prev_layer_ext_perim_lines,prev_layer_boundary, params);
+                                                                                         prev_layer_ext_perim_lines, prev_layer_boundary,
+                                                                                         params);
                     for (const ExtrusionLine &perim : perims) {
                         if (perim.support_point_generated.has_value()) {
                             reckon_new_support_point(*perim.support_point_generated, create_support_point_position(perim.b), -EPSILON,
@@ -932,6 +918,30 @@ std::tuple<SupportPoints, PartialObjects> check_stability(const PrintObject *po,
                         }
                     }
                 }
+                // DEBUG EXPORT, NOT USED NOW
+                // if (BR_bridge) {
+                //     Lines scaledl;
+                //     for (const auto &l : prev_layer_boundary.get_lines()) {
+                //         scaledl.emplace_back(Point::new_scale(l.a), Point::new_scale(l.b));
+                //     }
+
+                //     Lines perimsl;
+                //     for (const auto &l : current_slice_ext_perims_lines) {
+                //         perimsl.emplace_back(Point::new_scale(l.a), Point::new_scale(l.b));
+                //     }
+
+                //     BoundingBox bb = get_extents(scaledl);
+                //     bb.merge(get_extents(perimsl));
+
+                //     ::Slic3r::SVG svg(debug_out_path(
+                //                           ("slice" + std::to_string(slice_idx) + "_" + std::to_string(layer_idx).c_str()).c_str()),
+                //                       get_extents(scaledl));
+                //     svg.draw(scaledl, "red", scale_(0.4));
+                //     svg.draw(perimsl, "blue", scale_(0.25));
+                    
+                    
+                //     svg.Close();
+                // }
             }
 
             LD    current_slice_lines_distancer(current_slice_ext_perims_lines);

From d0c86403a52c0099e0202990b5078cd4aa09e9f7 Mon Sep 17 00:00:00 2001
From: PavelMikus <pavel.mikus.mail@seznam.cz>
Date: Thu, 26 Jan 2023 15:23:51 +0100
Subject: [PATCH 2/3] Fix lslices ordering - keep topological ordering from
 clipper, and separate print ordering into vector of indices

---
 src/libslic3r/GCode.cpp                 |  3 +-
 src/libslic3r/Layer.cpp                 | 41 ++++++++++++++-----------
 src/libslic3r/Layer.hpp                 |  1 +
 src/libslic3r/PrintObjectSlice.cpp      |  2 +-
 src/libslic3r/SupportSpotsGenerator.cpp | 31 ++++++++++---------
 5 files changed, 43 insertions(+), 35 deletions(-)

diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index ffffd9d31..07031d7e4 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -2308,7 +2308,8 @@ void GCode::process_layer_single_object(
 
     ExtrusionEntitiesPtr temp_fill_extrusions;
     if (const Layer *layer = layer_to_print.object_layer; layer)
-        for (const LayerSlice &lslice : layer->lslices_ex) {
+        for (size_t idx : layer->lslice_indices_sorted_by_print_order) {
+            const LayerSlice &lslice = layer->lslices_ex[idx];
             auto extrude_infill_range = [&](
                 const LayerRegion &layerm, const ExtrusionEntityCollection &fills,
                 LayerExtrusionRanges::const_iterator it_fill_ranges_begin, LayerExtrusionRanges::const_iterator it_fill_ranges_end, bool ironing) {
diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp
index 9b0004e98..378352be7 100644
--- a/src/libslic3r/Layer.cpp
+++ b/src/libslic3r/Layer.cpp
@@ -38,32 +38,37 @@ LayerRegion* Layer::add_region(const PrintRegion *print_region)
 // merge all regions' slices to get islands
 void Layer::make_slices()
 {
-    ExPolygons slices;
-    if (m_regions.size() == 1) {
-        // optimization: if we only have one region, take its slices
-        slices = to_expolygons(m_regions.front()->slices().surfaces);
-    } else {
-        Polygons slices_p;
-        for (LayerRegion *layerm : m_regions)
-            polygons_append(slices_p, to_polygons(layerm->slices().surfaces));
-        slices = union_safety_offset_ex(slices_p);
+    {
+        ExPolygons slices;
+        if (m_regions.size() == 1) {
+            // optimization: if we only have one region, take its slices
+            slices = to_expolygons(m_regions.front()->slices().surfaces);
+        } else {
+            Polygons slices_p;
+            for (LayerRegion *layerm : m_regions)
+                polygons_append(slices_p, to_polygons(layerm->slices().surfaces));
+            slices = union_safety_offset_ex(slices_p);
+        }
+        // lslices are sorted by topological order from outside to inside from the clipper union used above
+        this->lslices = slices;
     }
-    
-    this->lslices.clear();
-    this->lslices.reserve(slices.size());
-    
+
+    // prepare lslices ordered by print order
+    this->lslice_indices_sorted_by_print_order.clear();
+    this->lslice_indices_sorted_by_print_order.reserve(lslices.size());
     // prepare ordering points
     Points ordering_points;
-    ordering_points.reserve(slices.size());
-    for (const ExPolygon &ex : slices)
+    ordering_points.reserve( this->lslices.size());
+    for (const ExPolygon &ex :  this->lslices)
         ordering_points.push_back(ex.contour.first_point());
     
     // sort slices
     std::vector<Points::size_type> order = chain_points(ordering_points);
-    
+
     // populate slices vector
-    for (size_t i : order)
-        this->lslices.emplace_back(std::move(slices[i]));
+    for (size_t i : order) {
+        this->lslice_indices_sorted_by_print_order.emplace_back(i);
+    }
 }
 
 // used by Layer::build_up_down_graph()
diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp
index cfeace67b..11193828c 100644
--- a/src/libslic3r/Layer.hpp
+++ b/src/libslic3r/Layer.hpp
@@ -336,6 +336,7 @@ public:
     // 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.
     ExPolygons 				lslices;
+    std::vector<size_t>     lslice_indices_sorted_by_print_order;
     LayerSlices             lslices_ex;
 
     size_t                  region_count() const { return m_regions.size(); }
diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp
index 81e21f305..0d950b93e 100644
--- a/src/libslic3r/PrintObjectSlice.cpp
+++ b/src/libslic3r/PrintObjectSlice.cpp
@@ -799,7 +799,7 @@ void PrintObject::slice_volumes()
 	                            layer->m_regions[region_id]->trim_surfaces(trimming);
 	                    }
 	                }
-	                // Merge all regions' slices to get islands, chain them by a shortest path.
+	                // Merge all regions' slices to get islands sorted topologically, chain them by a shortest path in separate index list
 	                layer->make_slices();
 	            }
 	        });
diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp
index 9bf9dbdef..47e7228d4 100644
--- a/src/libslic3r/SupportSpotsGenerator.cpp
+++ b/src/libslic3r/SupportSpotsGenerator.cpp
@@ -1175,13 +1175,6 @@ void raise_alerts_for_issues(const SupportPoints
                              PartialObjects                                                      &partial_objects,
                              std::function<void(PrintStateBase::WarningLevel, SupportPointCause)> alert_fn)
 {
-    for (const SupportPoint &sp : support_points) {
-        if (sp.cause == SupportPointCause::SeparationFromBed) {
-                alert_fn(PrintStateBase::WarningLevel::NON_CRITICAL, SupportPointCause::SeparationFromBed);
-                break;
-        }
-    }
-
     std::reverse(partial_objects.begin(), partial_objects.end());
     std::sort(partial_objects.begin(), partial_objects.end(),
               [](const PartialObject &left, const PartialObject &right) { return left.volume > right.volume; });
@@ -1231,21 +1224,29 @@ void raise_alerts_for_issues(const SupportPoints
         }
     }
 
-    if (ext_supp_points.size() > 5) {
-        alert_fn(PrintStateBase::WarningLevel::NON_CRITICAL, SupportPointCause::FloatingExtrusion);
-    }
-
     for (const SupportPoint &sp : support_points) {
-        if (sp.cause == SupportPointCause::LongBridge) {
-                alert_fn(PrintStateBase::WarningLevel::NON_CRITICAL, SupportPointCause::LongBridge);
-                break;
+        if (sp.cause == SupportPointCause::SeparationFromBed) {
+                alert_fn(PrintStateBase::WarningLevel::NON_CRITICAL, SupportPointCause::SeparationFromBed);
+                return;
         }
     }
 
     for (const SupportPoint &sp : support_points) {
         if (sp.cause == SupportPointCause::WeakObjectPart) {
                 alert_fn(PrintStateBase::WarningLevel::NON_CRITICAL, SupportPointCause::WeakObjectPart);
-                break;
+                return;
+        }
+    }
+
+    if (ext_supp_points.size() > 5) {
+        alert_fn(PrintStateBase::WarningLevel::NON_CRITICAL, SupportPointCause::FloatingExtrusion);
+        return;
+    }
+
+    for (const SupportPoint &sp : support_points) {
+        if (sp.cause == SupportPointCause::LongBridge) {
+                alert_fn(PrintStateBase::WarningLevel::NON_CRITICAL, SupportPointCause::LongBridge);
+                return;
         }
     }
 }

From d16f9e0410f29ad8370a045b20e747470f92a495 Mon Sep 17 00:00:00 2001
From: PavelMikus <pavel.mikus.mail@seznam.cz>
Date: Thu, 26 Jan 2023 15:51:53 +0100
Subject: [PATCH 3/3] add check button for disabling the support alerts

---
 src/libslic3r/Preset.cpp         | 2 +-
 src/libslic3r/PrintConfig.cpp    | 8 ++++++++
 src/libslic3r/PrintConfig.hpp    | 1 +
 src/libslic3r/PrintObject.cpp    | 4 +++-
 src/slic3r/GUI/GUI_Factories.cpp | 2 +-
 src/slic3r/GUI/Tab.cpp           | 1 +
 6 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp
index d6a4692f3..76f784d6d 100644
--- a/src/libslic3r/Preset.cpp
+++ b/src/libslic3r/Preset.cpp
@@ -444,7 +444,7 @@ static std::vector<std::string> s_Preset_print_options {
     "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed",
     "bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "first_layer_speed_over_raft", "perimeter_acceleration", "infill_acceleration",
     "bridge_acceleration", "first_layer_acceleration", "first_layer_acceleration_over_raft", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield",
-    "min_skirt_length", "brim_width", "brim_separation", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers",
+    "min_skirt_length", "brim_width", "brim_separation", "brim_type", "check_for_issues_mode", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers",
     "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
     "support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_closing_radius", "support_material_style",
     "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", "support_material_bottom_interface_layers",
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index 779261abd..8c0b0f928 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -2589,6 +2589,14 @@ void PrintConfigDef::init_fff_params()
     def->mode = comAdvanced;
     def->set_default_value(new ConfigOptionEnum<SlicingMode>(SlicingMode::Regular));
 
+    def           = this->add("check_for_issues_mode", coBool);
+    def->label    = L("Check for issues: ");
+    def->category = L("Support material");
+    def->tooltip  = L("Check for supportable issues that may appear during printing. "
+                       "If enabled, slicer will make alerts when it detects "
+                       "issues that may be resolved with supports and/or brim.");
+    def->set_default_value(new ConfigOptionBool(true));
+
     def = this->add("support_material", coBool);
     def->label = L("Generate support material");
     def->category = L("Support material");
diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp
index 6bfc7723d..bdf82e3be 100644
--- a/src/libslic3r/PrintConfig.hpp
+++ b/src/libslic3r/PrintConfig.hpp
@@ -516,6 +516,7 @@ PRINT_CONFIG_CLASS_DEFINE(
     ((ConfigOptionInt,                 wall_distribution_count))
     ((ConfigOptionFloatOrPercent,      min_feature_size))
     ((ConfigOptionFloatOrPercent,      min_bead_width))
+    ((ConfigOptionBool,                check_for_issues_mode))
     ((ConfigOptionBool,                support_material))
     // Automatic supports (generated based fdm support point generator).
     ((ConfigOptionBool,                support_material_auto))
diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp
index 82b69baa3..8fc016950 100644
--- a/src/libslic3r/PrintObject.cpp
+++ b/src/libslic3r/PrintObject.cpp
@@ -462,7 +462,7 @@ void PrintObject::generate_support_spots()
                 }
             };
 
-            if (!this->has_support()) {
+            if (!this->has_support() && this->config().check_for_issues_mode.getBool())  {
                 SupportSpotsGenerator::raise_alerts_for_issues(supp_points, partial_objects, alert_fn);
             }
         }
@@ -619,6 +619,8 @@ bool PrintObject::invalidate_state_by_config_options(
             steps.emplace_back(posSupportSpotsSearch);
             // Brim is printed below supports, support invalidates brim and skirt.
             steps.emplace_back(posSupportMaterial);
+        }else if (opt_key == "check_for_issues_mode") {
+            steps.emplace_back(posSupportSpotsSearch);
         } else if (
                opt_key == "perimeters"
             || opt_key == "extra_perimeters"
diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp
index c06947565..cbe1805ee 100644
--- a/src/slic3r/GUI/GUI_Factories.cpp
+++ b/src/slic3r/GUI/GUI_Factories.cpp
@@ -53,7 +53,7 @@ static SettingsFactory::Bundle FREQ_SETTINGS_BUNDLE_FFF =
 {
     { L("Layers and Perimeters"), { "layer_height" , "perimeters", "top_solid_layers", "bottom_solid_layers" } },
     { L("Infill")               , { "fill_density", "fill_pattern" } },
-    { L("Support material")     , { "support_material", "support_material_auto", "support_material_threshold",
+    { L("Support material")     , { "check_for_issues_mode", "support_material", "support_material_auto", "support_material_threshold",
                                     "support_material_pattern", "support_material_interface_pattern", "support_material_buildplate_only",
                                     "support_material_spacing" } },
     { L("Wipe options")         , { "wipe_into_infill", "wipe_into_objects" } }
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index 43eaa1a22..e9c854774 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -1495,6 +1495,7 @@ void TabPrint::build()
     page = add_options_page(L("Support material"), "support");
         category_path = "support-material_1698#";
         optgroup = page->new_optgroup(L("Support material"));
+        optgroup->append_single_option_line("check_for_issues_mode", category_path + "check-for-issues-mode");
         optgroup->append_single_option_line("support_material", category_path + "generate-support-material");
         optgroup->append_single_option_line("support_material_auto", category_path + "auto-generated-supports");
         optgroup->append_single_option_line("support_material_threshold", category_path + "overhang-threshold");