diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index 3f2327686..39228516c 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -4,6 +4,7 @@ #include "Fill/Fill.hpp" #include "ShortestPath.hpp" #include "SVG.hpp" +#include "BoundingBox.hpp" #include @@ -258,4 +259,26 @@ void Layer::export_region_fill_surfaces_to_svg_debug(const char *name) const this->export_region_fill_surfaces_to_svg(debug_out_path("Layer-fill_surfaces-%s-%d.svg", name, idx ++).c_str()); } +BoundingBox get_extents(const LayerRegion &layer_region) +{ + BoundingBox bbox; + if (!layer_region.slices.surfaces.empty()) { + bbox = get_extents(layer_region.slices.surfaces.front()); + for (auto it = layer_region.slices.surfaces.cbegin() + 1; it != layer_region.slices.surfaces.cend(); ++it) + bbox.merge(get_extents(*it)); + } + return bbox; +} + +BoundingBox get_extents(const LayerRegionPtrs &layer_regions) +{ + BoundingBox bbox; + if (!layer_regions.empty()) { + bbox = get_extents(*layer_regions.front()); + for (auto it = layer_regions.begin() + 1; it != layer_regions.end(); ++it) + bbox.merge(get_extents(**it)); + } + return bbox; +} + } diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 6cabdeb40..e6bf4b4fc 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -211,6 +211,9 @@ inline std::vector zs_from_layers(const LayerContainer &layers) return zs; } +extern BoundingBox get_extents(const LayerRegion &layer_region); +extern BoundingBox get_extents(const LayerRegionPtrs &layer_regions); + } #endif diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index c79cfecc1..65284ffac 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -42,6 +42,7 @@ struct segment_traits { //#define MMU_SEGMENTATION_DEBUG_GRAPH //#define MMU_SEGMENTATION_DEBUG_REGIONS +//#define MMU_SEGMENTATION_DEBUG_INPUT namespace Slic3r { @@ -1699,6 +1700,22 @@ static void export_graph_to_svg(const std::string &path, const MMU_Graph &graph, } #endif // MMU_SEGMENTATION_DEBUG_GRAPH +#ifdef MMU_SEGMENTATION_DEBUG_INPUT +void export_processed_input_expolygons_to_svg(const std::string &path, const LayerRegionPtrs ®ions, const ExPolygons &processed_input_expolygons) +{ + coordf_t stroke_width = scale_(0.05); + BoundingBox bbox = get_extents(regions); + bbox.merge(get_extents(processed_input_expolygons)); + bbox.offset(scale_(1.)); + ::Slic3r::SVG svg(path.c_str(), bbox); + + for (LayerRegion *region : regions) + svg.draw_outline(region->slices.surfaces, "blue", "cyan", stroke_width); + + svg.draw_outline(processed_input_expolygons, "red", "pink", stroke_width); +} +#endif // MMU_SEGMENTATION_DEBUG_INPUT + std::vector>> multi_material_segmentation_by_painting(const PrintObject &print_object, const std::function &throw_on_cancel_callback) { std::vector>> segmented_regions(print_object.layers().size()); @@ -1732,13 +1749,21 @@ std::vector>> multi_material_segmentati // This consequently leads to issues with the extraction of colored segments by function extract_colored_segments. // Calling expolygons_simplify fixed these issues. input_expolygons[layer_idx] = smooth_outward(expolygons_simplify(offset_ex(ex_polygons, -10.f * float(SCALED_EPSILON)), 5 * SCALED_EPSILON), 10 * coord_t(SCALED_EPSILON)); + +#ifdef MMU_SEGMENTATION_DEBUG_INPUT + { + static int iRun = 0; + export_processed_input_expolygons_to_svg(debug_out_path("mm-input-%d-%d.svg", layer_idx, iRun++), layers[layer_idx]->regions(), input_expolygons[layer_idx]); + } +#endif // MMU_SEGMENTATION_DEBUG_INPUT } }); // end of parallel_for BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - end"; for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) { throw_on_cancel_callback(); - BoundingBox bbox(get_extents(input_expolygons[layer_idx])); + BoundingBox bbox(get_extents(layers[layer_idx]->regions())); + bbox.merge(get_extents(input_expolygons[layer_idx])); // Projected triangles may slightly exceed the input polygons. bbox.offset(20 * SCALED_EPSILON); edge_grids[layer_idx].set_bbox(bbox); @@ -1748,7 +1773,7 @@ std::vector>> multi_material_segmentati BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - projection of painted triangles - begin"; for (const ModelVolume *mv : print_object.model_object()->volumes) { const size_t num_extruders = print_object.print()->config().nozzle_diameter.size() + 1; - tbb::parallel_for(tbb::blocked_range(1, num_extruders), [&mv, &print_object, &edge_grids, &painted_lines, &painted_lines_mutex, &throw_on_cancel_callback](const tbb::blocked_range &range) { + tbb::parallel_for(tbb::blocked_range(1, num_extruders), [&mv, &print_object, &edge_grids, &painted_lines, &painted_lines_mutex, &input_expolygons, &throw_on_cancel_callback](const tbb::blocked_range &range) { for (size_t extruder_idx = range.begin(); extruder_idx < range.end(); ++extruder_idx) { throw_on_cancel_callback(); const indexed_triangle_set custom_facets = mv->mmu_segmentation_facets.get_facets(*mv, EnforcerBlockerType(extruder_idx)); @@ -1756,7 +1781,7 @@ std::vector>> multi_material_segmentati continue; const Transform3f tr = print_object.trafo().cast() * mv->get_matrix().cast(); - tbb::parallel_for(tbb::blocked_range(0, custom_facets.indices.size()), [&tr, &custom_facets, &print_object, &edge_grids, &painted_lines, &painted_lines_mutex, &extruder_idx](const tbb::blocked_range &range) { + tbb::parallel_for(tbb::blocked_range(0, custom_facets.indices.size()), [&tr, &custom_facets, &print_object, &edge_grids, &input_expolygons, &painted_lines, &painted_lines_mutex, &extruder_idx](const tbb::blocked_range &range) { for (size_t facet_idx = range.begin(); facet_idx < range.end(); ++facet_idx) { float min_z = std::numeric_limits::max(); float max_z = std::numeric_limits::lowest(); @@ -1781,7 +1806,7 @@ std::vector>> multi_material_segmentati for (auto layer_it = first_layer; layer_it != (last_layer + 1); ++layer_it) { const Layer *layer = *layer_it; size_t layer_idx = layer_it - print_object.layers().begin(); - if (facet[0].z() > layer->slice_z || layer->slice_z > facet[2].z()) + if (input_expolygons[layer_idx].empty() || facet[0].z() > layer->slice_z || layer->slice_z > facet[2].z()) continue; // https://kandepet.com/3d-printing-slicing-3d-objects/