From 368b48b0a0b738145d67f633379ff8cdf20cbb9e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= <hejl.lukas@gmail.com>
Date: Mon, 19 Apr 2021 07:12:42 +0200
Subject: [PATCH] WIP: Allows regions of MMU segmentation to be trimmed by
 chosen width.

---
 src/libslic3r/Preset.cpp      |  2 +-
 src/libslic3r/Print.cpp       |  2 ++
 src/libslic3r/PrintConfig.cpp |  8 ++++++++
 src/libslic3r/PrintConfig.hpp |  2 ++
 src/libslic3r/PrintObject.cpp | 18 ++++++++++++++++++
 src/slic3r/GUI/Tab.cpp        |  1 +
 6 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp
index 7db61a20f..5f0e1f99e 100644
--- a/src/libslic3r/Preset.cpp
+++ b/src/libslic3r/Preset.cpp
@@ -438,7 +438,7 @@ const std::vector<std::string>& Preset::print_options()
         "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width",
         "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "infill_anchor", "infill_anchor_max", "bridge_flow_ratio", "clip_multipart_objects",
         "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y",
-        "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming",
+        "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width",
         "wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits"
     };
     return s_opts;
diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp
index 8e23e2767..c8ab9b2c2 100644
--- a/src/libslic3r/Print.cpp
+++ b/src/libslic3r/Print.cpp
@@ -227,6 +227,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
             osteps.emplace_back(posSupportMaterial);
             steps.emplace_back(psSkirt);
             steps.emplace_back(psBrim);
+        } else if (opt_key == "mmu_segmented_region_max_width") {
+            invalidated |= this->invalidate_all_steps();
         } else {
             // for legacy, if we can't handle this option let's invalidate all steps
             //FIXME invalidate all steps of all objects as well?
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index 5516b298d..3280fe0a9 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -1288,6 +1288,14 @@ void PrintConfigDef::init_fff_params()
     def->mode = comExpert;
     def->set_default_value(new ConfigOptionBool(false));
 
+    def = this->add("mmu_segmented_region_max_width", coFloat);
+    def->label = L("Maximum width of a segmented region");
+    def->tooltip = L("Maximum width of a segmented region. Zero disables this feature.");
+    def->sidetext = L("mm (zero to disable)");
+    def->min = 0;
+    def->mode = comExpert;
+    def->set_default_value(new ConfigOptionFloat(0.f));
+
     def = this->add("ironing", coBool);
     def->label = L("Enable ironing");
     def->tooltip = L("Enable ironing of the top layers with the hot print head for smooth surface");
diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp
index aab509662..7c50827ff 100644
--- a/src/libslic3r/PrintConfig.hpp
+++ b/src/libslic3r/PrintConfig.hpp
@@ -962,6 +962,7 @@ public:
     ConfigOptionFloat               max_print_height;
     ConfigOptionFloats              min_print_speed;
     ConfigOptionFloat               min_skirt_length;
+    ConfigOptionFloat               mmu_segmented_region_max_width;
     ConfigOptionString              notes;
     ConfigOptionFloats              nozzle_diameter;
     ConfigOptionBool                only_retract_when_crossing_perimeters;
@@ -1037,6 +1038,7 @@ protected:
         OPT_PTR(max_print_height);
         OPT_PTR(min_print_speed);
         OPT_PTR(min_skirt_length);
+        OPT_PTR(mmu_segmented_region_max_width);
         OPT_PTR(notes);
         OPT_PTR(nozzle_diameter);
         OPT_PTR(only_retract_when_crossing_perimeters);
diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp
index e6abfe5a2..6dc87499c 100644
--- a/src/libslic3r/PrintObject.cpp
+++ b/src/libslic3r/PrintObject.cpp
@@ -4182,6 +4182,21 @@ static void remove_multiple_edges_in_vertices(MMU_Graph &graph, const std::vecto
     }
 }
 
+static void cut_segmented_layers(const LayerPtrs &layers, std::vector<std::vector<std::pair<ExPolygon, size_t>>> &segmented_regions, const float cut_width) {
+    tbb::parallel_for(tbb::blocked_range<size_t>(0, segmented_regions.size()),[&](const tbb::blocked_range<size_t>& range) {
+        for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
+            std::vector<std::pair<ExPolygon, size_t>> segmented_regions_cuts;
+            for (const std::pair<ExPolygon, size_t> &colored_expoly : segmented_regions[layer_idx]) {
+                ExPolygons cut_colored_expoly = diff_ex({colored_expoly.first}, offset_ex(layers[layer_idx]->lslices, cut_width));
+                for (const ExPolygon &expoly : cut_colored_expoly) {
+                    segmented_regions_cuts.emplace_back(expoly, colored_expoly.second);
+                }
+            }
+            segmented_regions[layer_idx] = segmented_regions_cuts;
+        }
+    }); // end of parallel_for
+}
+
 std::vector<std::vector<std::pair<ExPolygon, size_t>>> PrintObject::mmu_segmentation_by_painting()
 {
     std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmented_regions(this->layers().size());
@@ -4309,6 +4324,9 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> PrintObject::mmu_segmenta
         }
     }); // end of parallel_for
 
+    if(m_print->config().mmu_segmented_region_max_width > 0.f)
+        cut_segmented_layers(m_layers, segmented_regions, float(-scale_(m_print->config().mmu_segmented_region_max_width)));
+
     return segmented_regions;
 }
 // --------------------MMU_END----------------------
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index 0e954a906..78ecc25c1 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -1586,6 +1586,7 @@ void TabPrint::build()
 
         optgroup = page->new_optgroup(L("Advanced"));
         optgroup->append_single_option_line("interface_shells");
+        optgroup->append_single_option_line("mmu_segmented_region_max_width");
 
     page = add_options_page(L("Advanced"), "wrench");
         optgroup = page->new_optgroup(L("Extrusion width"));