diff --git a/src/libslic3r/Feature/Interlocking/InterlockingGenerator.cpp b/src/libslic3r/Feature/Interlocking/InterlockingGenerator.cpp index a3e6cd21b0..726ee2ffd8 100644 --- a/src/libslic3r/Feature/Interlocking/InterlockingGenerator.cpp +++ b/src/libslic3r/Feature/Interlocking/InterlockingGenerator.cpp @@ -23,10 +23,11 @@ template<> struct hash namespace Slic3r { -void InterlockingGenerator::generate_interlocking_structure(PrintObject* print_object) +void InterlockingGenerator::generate_interlocking_structure(PrintObject* print_object, const std::function& throw_on_cancel) { const auto& config = print_object->config(); - if (!config.interlocking_beam) { + // Check if interlocking is enabled, and avoid errors like division by zero due to invalid configuration. + if (!config.interlocking_beam || config.interlocking_beam_layer_count < 1 || config.interlocking_depth < 1 || config.interlocking_beam_width < EPSILON ) { return; } @@ -55,8 +56,10 @@ void InterlockingGenerator::generate_interlocking_structure(PrintObject* print_o continue; } + throw_on_cancel(); + InterlockingGenerator gen(*print_object, region_a_index, region_b_index, beam_width, boundary_avoidance, rotation, cell_size, beam_layer_count, - interface_dilation, air_dilation, air_filtering); + interface_dilation, air_dilation, air_filtering, throw_on_cancel); gen.generateInterlockingStructure(); } } @@ -108,12 +111,14 @@ void InterlockingGenerator::handleThinAreas(const std::unordered_set } } for (auto& near_interlock : near_interlock_per_layer) { + throw_on_cancel(); near_interlock = offset(union_(closing(near_interlock, rounding_errors)), detect); polygons_rotate(near_interlock, rotation); } // Only alter layers when they are present in both meshes, zip should take care if that. for (size_t layer_nr = 0; layer_nr < print_object.layer_count(); layer_nr++){ + throw_on_cancel(); auto layer = print_object.get_layer(layer_nr); ExPolygons polys_a = to_expolygons(layer->get_region(region_a_index)->slices.surfaces); ExPolygons polys_b = to_expolygons(layer->get_region(region_b_index)->slices.surfaces); @@ -199,7 +204,8 @@ void InterlockingGenerator::addBoundaryCells(const std::vector& lay const DilationKernel& kernel, std::unordered_set& cells) const { - auto voxel_emplacer = [&cells](GridPoint3 p) { + auto voxel_emplacer = [this, &cells](GridPoint3 p) { + this->throw_on_cancel(); if (p.z() < 0) { return true; } @@ -313,6 +319,7 @@ void InterlockingGenerator::applyMicrostructureToOutlines(const std::unordered_s for (size_t region_idx = 0; region_idx < 2; region_idx++) { const size_t region = (region_idx == 0) ? region_a_index : region_b_index; for (size_t layer_nr = 0; layer_nr < max_layer_count; layer_nr++) { + throw_on_cancel(); ExPolygons layer_outlines = layer_regions[layer_nr]; expolygons_rotate(layer_outlines, unapply_rotation); diff --git a/src/libslic3r/Feature/Interlocking/InterlockingGenerator.hpp b/src/libslic3r/Feature/Interlocking/InterlockingGenerator.hpp index 6f331fb8ef..e6b79f9bc8 100644 --- a/src/libslic3r/Feature/Interlocking/InterlockingGenerator.hpp +++ b/src/libslic3r/Feature/Interlocking/InterlockingGenerator.hpp @@ -45,7 +45,7 @@ public: /*! * Generate an interlocking structure between each two adjacent meshes. */ - static void generate_interlocking_structure(PrintObject* print_object); + static void generate_interlocking_structure(PrintObject* print_object, const std::function& throw_on_cancel); private: /*! @@ -75,7 +75,8 @@ private: const coord_t beam_layer_count, const DilationKernel& interface_dilation, const DilationKernel& air_dilation, - const bool air_filtering) + const bool air_filtering, + const std::function& throw_on_cancel) : print_object(print_object) , region_a_index(region_a_index) , region_b_index(region_b_index) @@ -88,6 +89,7 @@ private: , interface_dilation(interface_dilation) , air_dilation(air_dilation) , air_filtering(air_filtering) + , throw_on_cancel(throw_on_cancel) {} /*! Given two polygons, return the parts that border on air, and grow 'perpendicular' up to 'detect' distance. @@ -165,6 +167,8 @@ private: // Whether to fully remove all of the interlocking cells which would be visible on the outside. If no air filtering then those cells // will be cut off midway in a beam. const bool air_filtering; + + const std::function& throw_on_cancel; }; } // namespace Slic3r diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index 532307414d..2d67ac0939 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -1212,7 +1212,7 @@ void PrintObject::slice_volumes() apply_fuzzy_skin_segmentation(*this, [print]() { print->throw_if_canceled(); }); } - InterlockingGenerator::generate_interlocking_structure(this); + InterlockingGenerator::generate_interlocking_structure(this, [print]() { print->throw_if_canceled(); }); m_print->throw_if_canceled(); BOOST_LOG_TRIVIAL(debug) << "Slicing volumes - make_slices in parallel - begin";