From 168b4afbc21876e6b4797658e907f33e767a920f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Mon, 3 May 2021 20:37:14 +0200 Subject: [PATCH] Fixed MMU segmentation for multi-volume objects. MMU segmentation no longer works directly on lslices, instead of it works on custom merged regions. So lslices in PrintObject are no longer overwritten because of MMU segmentation. All regions are scaled by SCALED_EPSILON before merging and shrunk back by SCALED_EPSILON after merging. That fixed issues with multi-volume objects when very close regions weren't merged. Also, small expolygons and holes are filtered out that fixed missing segmentation at the boundary of two volumes in the case of multi-volume objects. --- src/libslic3r/ExPolygon.cpp | 21 +++++++++++++++++ src/libslic3r/ExPolygon.hpp | 3 +++ src/libslic3r/MultiMaterialSegmentation.cpp | 26 ++++++++++++++------- src/libslic3r/PrintObject.cpp | 9 ------- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/libslic3r/ExPolygon.cpp b/src/libslic3r/ExPolygon.cpp index 489023041f..506ba8cb6f 100644 --- a/src/libslic3r/ExPolygon.cpp +++ b/src/libslic3r/ExPolygon.cpp @@ -372,6 +372,27 @@ bool remove_sticks(ExPolygon &poly) return remove_sticks(poly.contour) || remove_sticks(poly.holes); } +bool remove_small_and_small_holes(ExPolygons &expolygons, double min_area) +{ + bool modified = false; + size_t free_idx = 0; + for (size_t expoly_idx = 0; expoly_idx < expolygons.size(); ++expoly_idx) { + if (std::abs(expolygons[expoly_idx].area()) >= min_area) { + // Expolygon is big enough, so also check all its holes + modified |= remove_small(expolygons[expoly_idx].holes, min_area); + if (free_idx < expoly_idx) { + std::swap(expolygons[expoly_idx].contour, expolygons[free_idx].contour); + std::swap(expolygons[expoly_idx].holes, expolygons[free_idx].holes); + } + ++free_idx; + } else + modified = true; + } + if (free_idx < expolygons.size()) + expolygons.erase(expolygons.begin() + free_idx, expolygons.end()); + return modified; +} + void keep_largest_contour_only(ExPolygons &polygons) { if (polygons.size() > 1) { diff --git a/src/libslic3r/ExPolygon.hpp b/src/libslic3r/ExPolygon.hpp index 73770bb185..89ba2e0068 100644 --- a/src/libslic3r/ExPolygon.hpp +++ b/src/libslic3r/ExPolygon.hpp @@ -360,6 +360,9 @@ extern std::vector get_extents_vector(const ExPolygons &polygons); extern bool remove_sticks(ExPolygon &poly); extern void keep_largest_contour_only(ExPolygons &polygons); +// Removes all expolygons smaller than min_area and also removes all holes smaller than min_area +extern bool remove_small_and_small_holes(ExPolygons &expolygons, double min_area); + inline double area(const ExPolygons &polys) { double s = 0.; diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index aa25361083..1ed08ef4b9 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -1357,13 +1357,27 @@ std::vector>> multi_material_segmentati std::vector> painted_lines(print_object.layers().size()); std::vector edge_grids(print_object.layers().size()); const ConstLayerPtrsAdaptor layers = print_object.layers(); + std::vector input_polygons(layers.size()); + + // Merge all regions and remove small holes + for(size_t layer_idx = 0; layer_idx < layers.size(); layer_idx += 1) { + ExPolygons ex_polygons; + for (LayerRegion *region : layers[layer_idx]->regions()) + for (const Surface &surface : region->slices.surfaces) + Slic3r::append(ex_polygons, offset_ex(surface.expolygon, SCALED_EPSILON)); + // All expolygons are expanded by SCALED_EPSILON, merged, and then shrunk again by SCALED_EPSILON + // to ensure that very close polygons will be merged. + ex_polygons = union_ex(ex_polygons); + // Remove all expolygons and holes with an area less than 0.01mm^2 + remove_small_and_small_holes(ex_polygons, Slic3r::sqr(scale_(0.1f))); + input_polygons[layer_idx] = to_polygons(union_ex(offset_ex(ex_polygons, -SCALED_EPSILON))); + } for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) { - const Layer *layer = layers[layer_idx]; - BoundingBox bbox(get_extents(layer->lslices)); + BoundingBox bbox(get_extents(input_polygons[layer_idx])); bbox.offset(SCALED_EPSILON); edge_grids[layer_idx].set_bbox(bbox); - edge_grids[layer_idx].create(layer->lslices, coord_t(scale_(10.))); + edge_grids[layer_idx].create(input_polygons[layer_idx], coord_t(scale_(10.))); } for (const ModelVolume *mv : print_object.model_object()->volumes) { @@ -1453,11 +1467,7 @@ std::vector>> multi_material_segmentati std::vector &painted_lines_single = painted_lines[layer_idx]; if (!painted_lines_single.empty()) { - Polygons original_polygons; - for (const Slic3r::EdgeGrid::Contour &contour : edge_grids[layer_idx].contours()) - original_polygons.emplace_back(Points(contour.begin(), contour.end())); - - std::vector> color_poly = colorize_polygons(original_polygons, painted_lines_single); + std::vector> color_poly = colorize_polygons(input_polygons[layer_idx], painted_lines_single); MMU_Graph graph = build_graph(layer_idx, color_poly); remove_multiple_edges_in_vertices(graph, color_poly); graph.remove_nodes_with_one_arc(); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 1c5c4f0216..688b7d3607 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1906,15 +1906,6 @@ void PrintObject::_slice(const std::vector &layer_height_profile) // --------------------MMU_SEGMENTATION_BEGIN---------------------- - // Temporary fix for not assigned lslices - for(size_t layer_idx = 0; layer_idx < m_layers.size(); layer_idx += 1) { - ExPolygons ex_polygons; - for (LayerRegion *region : this->m_layers[layer_idx]->regions()) - for (const Surface &surface : region->slices.surfaces) - ex_polygons.emplace_back(surface.expolygon); - this->m_layers[layer_idx]->lslices = union_ex(ex_polygons); - } - size_t region_count_before_change = this->num_regions(); std::vector>> segmented_regions = multi_material_segmentation_by_painting(*this); // Skip region with default extruder