diff --git a/src/libslic3r/ExPolygon.cpp b/src/libslic3r/ExPolygon.cpp index 185e925084..d0550ec853 100644 --- a/src/libslic3r/ExPolygon.cpp +++ b/src/libslic3r/ExPolygon.cpp @@ -7,6 +7,7 @@ #include "ClipperUtils.hpp" #include "SVG.hpp" #include +#include #include #include @@ -407,11 +408,31 @@ BoundingBox get_extents(const ExPolygon &expolygon) BoundingBox get_extents(const ExPolygons &expolygons) { BoundingBox bbox; - if (! expolygons.empty()) { - for (size_t i = 0; i < expolygons.size(); ++ i) - if (! expolygons[i].contour.points.empty()) - bbox.merge(get_extents(expolygons[i])); + + const size_t n = expolygons.size(); + + BOOST_LOG_TRIVIAL(info) + << "get_extents ExPolygons addr=" << &expolygons + << " data=" << expolygons.data() + << " size=" << n + << " capacity=" << expolygons.capacity(); + + if (n > 1000000) { + BOOST_LOG_TRIVIAL(error) + << "Suspicious ExPolygons size=" << n + << " addr=" << &expolygons + << " data=" << expolygons.data() + << " capacity=" << expolygons.capacity(); + + assert(false); + return bbox; } + + for (size_t i = 0; i < n; ++i) { + if (!expolygons[i].contour.points.empty()) + bbox.merge(get_extents(expolygons[i])); + } + return bbox; } diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index 4946ad45c8..7da33edd45 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -1832,10 +1832,26 @@ static std::vector> merge_segmented_layers(const std::ve segmented_regions_merged.assign(num_layers, std::vector(num_facets_states - 1)); assert(!top_and_bottom_layers.size() || num_facets_states == top_and_bottom_layers.size()); + // Diagnostic: check initial state of second element (index 1) after assign + { + const size_t check_idx = num_facets_states - 2; // index of last element in inner vector + const auto &inner = segmented_regions_merged[0]; + BOOST_LOG_TRIVIAL(info) + << "merge_segmented_layers after assign" + << " inner_size=" << inner.size() + << " elem[" << check_idx << "].addr=" << &inner[check_idx] + << " data=" << inner[check_idx].data() + << " size=" << inner[check_idx].size() + << " capacity=" << inner[check_idx].capacity() + << " top_and_bottom_size=" << top_and_bottom_layers.size() + << " num_facets_states=" << num_facets_states; + } + BOOST_LOG_TRIVIAL(debug) << "Print object segmentation - Merging segmented layers in parallel - Begin"; tbb::parallel_for(tbb::blocked_range(0, num_layers), [&segmented_regions, &top_and_bottom_layers, &segmented_regions_merged, &num_facets_states, &throw_on_cancel_callback](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { assert(segmented_regions[layer_idx].size() == num_facets_states); + const size_t last_elem_idx = num_facets_states - 2; // index = num_facets_states - 1 - 1 // Zero is skipped because it is the default color of the volume for (size_t extruder_id = 1; extruder_id < num_facets_states; ++extruder_id) { throw_on_cancel_callback(); @@ -1860,6 +1876,39 @@ static std::vector> merge_segmented_layers(const std::ve if (!was_top_and_bottom_empty) segmented_regions_merged[layer_idx][extruder_id - 1] = offset2_ex(union_ex(segmented_regions_merged[layer_idx][extruder_id - 1]), float(SCALED_EPSILON), -float(SCALED_EPSILON)); } + + // Diagnostic: after processing this extruder_id, check the corresponding merged element + const size_t merged_idx = extruder_id - 1; + const auto &elem = segmented_regions_merged[layer_idx][merged_idx]; + if (elem.size() > 1000000) { + BOOST_LOG_TRIVIAL(error) + << "merge_segmented_layers CORRUPTION after extruder_id=" << extruder_id + << " layer_idx=" << layer_idx + << " merged_idx=" << merged_idx + << " elem_addr=" << &elem + << " data=" << elem.data() + << " size=" << elem.size() + << " capacity=" << elem.capacity() + << " top_and_bottom_empty=" << top_and_bottom_layers.empty() + << " tb_extruder_exists=" << (extruder_id < top_and_bottom_layers.size()) + << " segmented_src_data=" << segmented_regions[layer_idx][extruder_id].data() + << " segmented_src_size=" << segmented_regions[layer_idx][extruder_id].size(); + } + } + + // Diagnostic: final state of the last element after all extruders processed + const auto &last_elem = segmented_regions_merged[layer_idx][last_elem_idx]; + if (last_elem.size() > 1000000 || (last_elem.size() == 0 && last_elem.data() != nullptr && reinterpret_cast(last_elem.data()) < 0x1000)) { + BOOST_LOG_TRIVIAL(error) + << "merge_segmented_layers BAD FINAL STATE" + << " layer_idx=" << layer_idx + << " last_elem_idx=" << last_elem_idx + << " addr=" << &last_elem + << " data=" << last_elem.data() + << " size=" << last_elem.size() + << " capacity=" << last_elem.capacity() + << " inner_vec_addr=" << &segmented_regions_merged[layer_idx] + << " inner_vec_size=" << segmented_regions_merged[layer_idx].size(); } } }); // end of parallel_for @@ -2195,7 +2244,7 @@ std::vector> segmentation_by_painting(const PrintObject // Returns multi-material segmentation based on painting in multi-material segmentation gizmo std::vector> multi_material_segmentation_by_painting(const PrintObject &print_object, const std::function &throw_on_cancel_callback) { - const size_t num_facets_states = print_object.print()->config().filament_colour.size() + 1; + const size_t num_facets_states = print_object.print()->config().filament_diameter.size() + 1; const float max_width = float(print_object.config().mmu_segmented_region_max_width.value); const float interlocking_depth = float(print_object.config().mmu_segmented_region_interlocking_depth.value); const bool interlocking_beam = print_object.config().interlocking_beam.value; diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index 1e59b44e30..d20b289157 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -873,7 +873,6 @@ static inline void apply_mm_segmentation(PrintObject &print_object, ThrowOnCance double z = print_object.get_layer(int(range.begin()))->slice_z; auto it_layer_range = layer_range_first(layer_ranges, z); // BBS - const size_t num_extruders = print_object.print()->config().filament_diameter.size(); struct ByExtruder { ExPolygons expolygons; @@ -893,12 +892,30 @@ static inline void apply_mm_segmentation(PrintObject &print_object, ThrowOnCance it_layer_range = layer_range_next(layer_ranges, it_layer_range, layer.slice_z); const PrintObjectRegions::LayerRangeRegions &layer_range = *it_layer_range; // Gather per extruder expolygons. + const size_t num_extruders = segmentation[layer_id].size(); by_extruder.assign(num_extruders, ByExtruder()); by_region.assign(layer.region_count(), ByRegion()); bool layer_split = false; for (size_t extruder_id = 0; extruder_id < num_extruders; ++ extruder_id) { ByExtruder ®ion = by_extruder[extruder_id]; + const auto &src_expolys = segmentation[layer_id][extruder_id]; + BOOST_LOG_TRIVIAL(info) + << "apply_mm_segmentation before move" + << " layer_id=" << layer_id + << " extruder_id=" << extruder_id + << " src_addr=" << &src_expolys + << " src_data=" << src_expolys.data() + << " src_size=" << src_expolys.size() + << " src_capacity=" << src_expolys.capacity(); append(region.expolygons, std::move(segmentation[layer_id][extruder_id])); + BOOST_LOG_TRIVIAL(info) + << "apply_mm_segmentation after move" + << " layer_id=" << layer_id + << " extruder_id=" << extruder_id + << " dst_addr=" << ®ion.expolygons + << " dst_data=" << region.expolygons.data() + << " dst_size=" << region.expolygons.size() + << " dst_capacity=" << region.expolygons.capacity(); if (! region.expolygons.empty()) { region.bbox = get_extents(region.expolygons); layer_split = true;