From bff32c9cdbcf30603d392777f02365d1bf009a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 12 May 2022 09:49:07 +0200 Subject: [PATCH 1/2] Added cancellation to Lightning infill. --- src/libslic3r/Fill/FillLightning.cpp | 4 ++-- src/libslic3r/Fill/FillLightning.hpp | 2 +- src/libslic3r/Fill/Lightning/Generator.cpp | 20 ++++++++++++-------- src/libslic3r/Fill/Lightning/Generator.hpp | 7 +++---- src/libslic3r/Fill/Lightning/Layer.cpp | 5 ++++- src/libslic3r/Fill/Lightning/Layer.hpp | 3 ++- src/libslic3r/PrintObject.cpp | 2 +- 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/libslic3r/Fill/FillLightning.cpp b/src/libslic3r/Fill/FillLightning.cpp index 447fd8057..2ba6fe017 100644 --- a/src/libslic3r/Fill/FillLightning.cpp +++ b/src/libslic3r/Fill/FillLightning.cpp @@ -21,9 +21,9 @@ void GeneratorDeleter::operator()(Generator *p) { delete p; } -GeneratorPtr build_generator(const PrintObject &print_object) +GeneratorPtr build_generator(const PrintObject &print_object, const std::function &throw_on_cancel_callback) { - return GeneratorPtr(new Generator(print_object)); + return GeneratorPtr(new Generator(print_object, throw_on_cancel_callback)); } } // namespace Slic3r::FillAdaptive diff --git a/src/libslic3r/Fill/FillLightning.hpp b/src/libslic3r/Fill/FillLightning.hpp index b4e7e35f1..941392103 100644 --- a/src/libslic3r/Fill/FillLightning.hpp +++ b/src/libslic3r/Fill/FillLightning.hpp @@ -14,7 +14,7 @@ class Generator; struct GeneratorDeleter { void operator()(Generator *p); }; using GeneratorPtr = std::unique_ptr; -GeneratorPtr build_generator(const PrintObject &print_object); +GeneratorPtr build_generator(const PrintObject &print_object, const std::function &throw_on_cancel_callback); class Filler : public Slic3r::Fill { diff --git a/src/libslic3r/Fill/Lightning/Generator.cpp b/src/libslic3r/Fill/Lightning/Generator.cpp index 0bdd1c7e8..b4c07a338 100644 --- a/src/libslic3r/Fill/Lightning/Generator.cpp +++ b/src/libslic3r/Fill/Lightning/Generator.cpp @@ -25,7 +25,7 @@ namespace Slic3r::FillLightning { -Generator::Generator(const PrintObject &print_object) +Generator::Generator(const PrintObject &print_object, const std::function &throw_on_cancel_callback) { const PrintConfig &print_config = print_object.print()->config(); const PrintObjectConfig &object_config = print_object.config(); @@ -47,11 +47,11 @@ Generator::Generator(const PrintObject &print_object) m_prune_length = coord_t(layer_thickness * std::tan(lightning_infill_prune_angle)); m_straightening_max_distance = coord_t(layer_thickness * std::tan(lightning_infill_straightening_angle)); - generateInitialInternalOverhangs(print_object); - generateTrees(print_object); + generateInitialInternalOverhangs(print_object, throw_on_cancel_callback); + generateTrees(print_object, throw_on_cancel_callback); } -void Generator::generateInitialInternalOverhangs(const PrintObject &print_object) +void Generator::generateInitialInternalOverhangs(const PrintObject &print_object, const std::function &throw_on_cancel_callback) { m_overhang_per_layer.resize(print_object.layers().size()); // FIXME: It can be adjusted to improve bonding between infill and perimeters. @@ -59,7 +59,8 @@ void Generator::generateInitialInternalOverhangs(const PrintObject &print_object Polygons infill_area_above; //Iterate from top to bottom, to subtract the overhang areas above from the overhang areas on the layer below, to get only overhang in the top layer where it is overhanging. - for (int layer_nr = int(print_object.layers().size()) - 1; layer_nr >= 0; layer_nr--) { + for (int layer_nr = int(print_object.layers().size()) - 1; layer_nr >= 0; --layer_nr) { + throw_on_cancel_callback(); Polygons infill_area_here; for (const LayerRegion* layerm : print_object.get_layer(layer_nr)->regions()) for (const Surface& surface : layerm->fill_surfaces.surfaces) @@ -80,7 +81,7 @@ const Layer& Generator::getTreesForLayer(const size_t& layer_id) const return m_lightning_layers[layer_id]; } -void Generator::generateTrees(const PrintObject &print_object) +void Generator::generateTrees(const PrintObject &print_object, const std::function &throw_on_cancel_callback) { m_lightning_layers.resize(print_object.layers().size()); // FIXME: It can be adjusted to improve bonding between infill and perimeters. @@ -89,11 +90,13 @@ void Generator::generateTrees(const PrintObject &print_object) std::vector infill_outlines(print_object.layers().size(), Polygons()); // For-each layer from top to bottom: - for (int layer_id = int(print_object.layers().size()) - 1; layer_id >= 0; layer_id--) + for (int layer_id = int(print_object.layers().size()) - 1; layer_id >= 0; layer_id--) { + throw_on_cancel_callback(); for (const LayerRegion *layerm : print_object.get_layer(layer_id)->regions()) for (const Surface &surface : layerm->fill_surfaces.surfaces) if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid) append(infill_outlines[layer_id], infill_wall_offset == 0 ? surface.expolygon : offset(surface.expolygon, infill_wall_offset)); + } // For various operations its beneficial to quickly locate nearby features on the polygon: const size_t top_layer_id = print_object.layers().size() - 1; @@ -102,6 +105,7 @@ void Generator::generateTrees(const PrintObject &print_object) // For-each layer from top to bottom: for (int layer_id = int(top_layer_id); layer_id >= 0; layer_id--) { + throw_on_cancel_callback(); Layer ¤t_lightning_layer = m_lightning_layers[layer_id]; const Polygons ¤t_outlines = infill_outlines[layer_id]; const BoundingBox ¤t_outlines_bbox = get_extents(current_outlines); @@ -109,7 +113,7 @@ void Generator::generateTrees(const PrintObject &print_object) // register all trees propagated from the previous layer as to-be-reconnected std::vector to_be_reconnected_tree_roots = current_lightning_layer.tree_roots; - current_lightning_layer.generateNewTrees(m_overhang_per_layer[layer_id], current_outlines, current_outlines_bbox, outlines_locator, m_supporting_radius, m_wall_supporting_radius); + current_lightning_layer.generateNewTrees(m_overhang_per_layer[layer_id], current_outlines, current_outlines_bbox, outlines_locator, m_supporting_radius, m_wall_supporting_radius, throw_on_cancel_callback); current_lightning_layer.reconnectRoots(to_be_reconnected_tree_roots, current_outlines, current_outlines_bbox, outlines_locator, m_supporting_radius, m_wall_supporting_radius); // Initialize trees for next lower layer from the current one. diff --git a/src/libslic3r/Fill/Lightning/Generator.hpp b/src/libslic3r/Fill/Lightning/Generator.hpp index b538c4dbe..d7e5f63f9 100644 --- a/src/libslic3r/Fill/Lightning/Generator.hpp +++ b/src/libslic3r/Fill/Lightning/Generator.hpp @@ -43,9 +43,8 @@ public: * This generator will pre-compute things in preparation of generating * Lightning Infill for the infill areas in that mesh. The infill areas must * already be calculated at this point. - * \param mesh The mesh to generate infill for. */ - explicit Generator(const PrintObject &print_object); + explicit Generator(const PrintObject &print_object, const std::function &throw_on_cancel_callback); /*! * Get a tree of paths generated for a certain layer of the mesh. @@ -69,12 +68,12 @@ protected: * only when support is generated. For this pattern, we also need to * generate overhang areas for the inside of the model. */ - void generateInitialInternalOverhangs(const PrintObject &print_object); + void generateInitialInternalOverhangs(const PrintObject &print_object, const std::function &throw_on_cancel_callback); /*! * Calculate the tree structure of all layers. */ - void generateTrees(const PrintObject &print_object); + void generateTrees(const PrintObject &print_object, const std::function &throw_on_cancel_callback); float m_infill_extrusion_width; diff --git a/src/libslic3r/Fill/Lightning/Layer.cpp b/src/libslic3r/Fill/Lightning/Layer.cpp index c996b9b7b..c381d5505 100644 --- a/src/libslic3r/Fill/Lightning/Layer.cpp +++ b/src/libslic3r/Fill/Lightning/Layer.cpp @@ -44,10 +44,12 @@ void Layer::generateNewTrees const BoundingBox& current_outlines_bbox, const EdgeGrid::Grid& outlines_locator, const coord_t supporting_radius, - const coord_t wall_supporting_radius + const coord_t wall_supporting_radius, + const std::function &throw_on_cancel_callback ) { DistanceField distance_field(supporting_radius, current_outlines, current_outlines_bbox, current_overhang); + throw_on_cancel_callback(); SparseNodeGrid tree_node_locator; fillLocator(tree_node_locator, current_outlines_bbox); @@ -56,6 +58,7 @@ void Layer::generateNewTrees // Determine next point from tree/outline areas via distance-field Point unsupported_location; while (distance_field.tryGetNextPoint(&unsupported_location)) { + throw_on_cancel_callback(); GroundingLocation grounding_loc = getBestGroundingLocation( unsupported_location, current_outlines, current_outlines_bbox, outlines_locator, supporting_radius, wall_supporting_radius, tree_node_locator); diff --git a/src/libslic3r/Fill/Lightning/Layer.hpp b/src/libslic3r/Fill/Lightning/Layer.hpp index cc79c15b5..87431fb1c 100644 --- a/src/libslic3r/Fill/Lightning/Layer.hpp +++ b/src/libslic3r/Fill/Lightning/Layer.hpp @@ -44,7 +44,8 @@ public: const BoundingBox& current_outlines_bbox, const EdgeGrid::Grid& outline_locator, coord_t supporting_radius, - coord_t wall_supporting_radius + coord_t wall_supporting_radius, + const std::function &throw_on_cancel_callback ); /*! Determine & connect to connection point in tree/outline. diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 9c6178f8b..eeaf1b13c 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -464,7 +464,7 @@ FillLightning::GeneratorPtr PrintObject::prepare_lightning_infill_data() break; } - return has_lightning_infill ? FillLightning::build_generator(std::as_const(*this)) : FillLightning::GeneratorPtr(); + return has_lightning_infill ? FillLightning::build_generator(std::as_const(*this), [this]() -> void { this->throw_if_canceled(); }) : FillLightning::GeneratorPtr(); } void PrintObject::clear_layers() From 7b28bdc41f4b0820b3de637e3f880d3a899ab1c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 12 May 2022 14:16:32 +0200 Subject: [PATCH 2/2] Fixed function lineSegmentPolygonsIntersection() in the Lightning infill that wasn't returns the intersection point. It fixed the issue that sometimes the Lightning infill produced extrusions that hung in the air without proper support. --- src/libslic3r/Fill/Lightning/TreeNode.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Fill/Lightning/TreeNode.cpp b/src/libslic3r/Fill/Lightning/TreeNode.cpp index 822550fc4..9ef509611 100644 --- a/src/libslic3r/Fill/Lightning/TreeNode.cpp +++ b/src/libslic3r/Fill/Lightning/TreeNode.cpp @@ -180,7 +180,11 @@ bool lineSegmentPolygonsIntersection(const Point& a, const Point& b, const EdgeG } visitor { outline_locator, a.cast(), b.cast() }; outline_locator.visit_cells_intersecting_line(a, b, visitor); - return visitor.d2min < double(within_max_dist) * double(within_max_dist); + if (visitor.d2min < double(within_max_dist) * double(within_max_dist)) { + result = Point(visitor.intersection_pt); + return true; + } + return false; } bool Node::realign(const Polygons& outlines, const EdgeGrid::Grid& outline_locator, std::vector& rerooted_parts)