mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-14 00:52:04 +00:00
Allow cancel during beam interlocking generation (#12759)
With certain irrational beam interlocking parameters, it will take a few minutes to complete the interlocking generation; even worse: cancellation doesn't work once it started. This PR fix that by adding cancellation check inside some of the most time consuming loops so it can be stopped ASAP. Also cherry picked a sanity check from https://github.com/bambulab/BambuStudio/pull/9925 by @mpaperno. Thanks! The following test project (which was modified from the upper PR by @mpaperno) took me more than 90s to complete with 0.1mm beam width: [Interloack-Test2.orca.3mf.txt](https://github.com/user-attachments/files/25975637/Interloack-Test2.orca.3mf.txt)
This commit is contained in:
@@ -23,10 +23,11 @@ template<> struct hash<Slic3r::GridPoint3>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
void InterlockingGenerator::generate_interlocking_structure(PrintObject* print_object)
|
||||
void InterlockingGenerator::generate_interlocking_structure(PrintObject* print_object, const std::function<void()>& 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<GridPoint3>
|
||||
}
|
||||
}
|
||||
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<ExPolygons>& lay
|
||||
const DilationKernel& kernel,
|
||||
std::unordered_set<GridPoint3>& 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);
|
||||
|
||||
|
||||
@@ -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<void()>& 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<void()>& 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<void()>& throw_on_cancel;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user