Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::FillLightning::Generator Class Reference

#include <src/libslic3r/Fill/Lightning/Generator.hpp>

+ Collaboration diagram for Slic3r::FillLightning::Generator:

Public Member Functions

 Generator (const PrintObject &print_object, const coordf_t fill_density, const std::function< void()> &throw_on_cancel_callback)
 
const LayergetTreesForLayer (const size_t &layer_id) const
 
float infilll_extrusion_width () const
 

Protected Member Functions

void generateInitialInternalOverhangs (const PrintObject &print_object, const std::function< void()> &throw_on_cancel_callback)
 
void generateTrees (const PrintObject &print_object, const std::function< void()> &throw_on_cancel_callback)
 

Protected Attributes

float m_infill_extrusion_width
 
coord_t m_supporting_radius
 
coord_t m_wall_supporting_radius
 
coord_t m_prune_length
 
coord_t m_straightening_max_distance
 
std::vector< Polygonsm_overhang_per_layer
 
std::vector< Layerm_lightning_layers
 

Detailed Description

Generates the Lightning Infill pattern.

The lightning infill pattern is designed to use a minimal amount of material to support the top skin of the print, while still printing with reasonably consistently flowing lines. It sacrifices strength completely in favour of top surface quality and reduced print time / material usage.

Lightning Infill is so named because the patterns it creates resemble a forked path with one main path and many small lines on the side. These paths grow out from the sides of the model just below where the top surface needs to be supported from the inside, so that minimal material is needed.

This pattern is based on a paper called "Ribbed Support Vaults for 3D Printing of Hollowed Objects" by Tricard, Claux and Lefebvre: https://www.researchgate.net/publication/333808588_Ribbed_Support_Vaults_for_3D_Printing_of_Hollowed_Objects

Constructor & Destructor Documentation

◆ Generator()

Slic3r::FillLightning::Generator::Generator ( const PrintObject print_object,
const coordf_t  fill_density,
const std::function< void()> &  throw_on_cancel_callback 
)
explicit

Create a generator to fill a certain mesh with infill.

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.

28{
29 const PrintConfig &print_config = print_object.print()->config();
30 const PrintObjectConfig &object_config = print_object.config();
31 const PrintRegionConfig &region_config = print_object.shared_regions()->all_regions.front()->config();
32 const std::vector<double> &nozzle_diameters = print_config.nozzle_diameter.values;
33 double max_nozzle_diameter = *std::max_element(nozzle_diameters.begin(), nozzle_diameters.end());
34// const int infill_extruder = region_config.infill_extruder.value;
35 const double default_infill_extrusion_width = Flow::auto_extrusion_width(FlowRole::frInfill, float(max_nozzle_diameter));
36 // Note: There's not going to be a layer below the first one, so the 'initial layer height' doesn't have to be taken into account.
37 const double layer_thickness = scaled<double>(object_config.layer_height.value);
38
39 m_infill_extrusion_width = scaled<float>(region_config.infill_extrusion_width.percent ? default_infill_extrusion_width * 0.01 * region_config.infill_extrusion_width :
40 region_config.infill_extrusion_width != 0. ? region_config.infill_extrusion_width :
41 default_infill_extrusion_width);
43
44 const double lightning_infill_overhang_angle = M_PI / 4; // 45 degrees
45 const double lightning_infill_prune_angle = M_PI / 4; // 45 degrees
46 const double lightning_infill_straightening_angle = M_PI / 4; // 45 degrees
47 m_wall_supporting_radius = coord_t(layer_thickness * std::tan(lightning_infill_overhang_angle));
48 m_prune_length = coord_t(layer_thickness * std::tan(lightning_infill_prune_angle));
49 m_straightening_max_distance = coord_t(layer_thickness * std::tan(lightning_infill_straightening_angle));
50
51 generateInitialInternalOverhangs(print_object, throw_on_cancel_callback);
52 generateTrees(print_object, throw_on_cancel_callback);
53}
#define M_PI
Definition ExtrusionSimulator.cpp:20
coord_t m_prune_length
Definition Generator.hpp:101
coord_t m_supporting_radius
Definition Generator.hpp:83
void generateInitialInternalOverhangs(const PrintObject &print_object, const std::function< void()> &throw_on_cancel_callback)
Definition Generator.cpp:55
float m_infill_extrusion_width
Definition Generator.hpp:78
void generateTrees(const PrintObject &print_object, const std::function< void()> &throw_on_cancel_callback)
Definition Generator.cpp:86
coord_t m_straightening_max_distance
Definition Generator.hpp:111
coord_t m_wall_supporting_radius
Definition Generator.hpp:92
static float auto_extrusion_width(FlowRole role, float nozzle_diameter)
Definition Flow.cpp:18
int32_t coord_t
Definition libslic3r.h:39
fill_density((ConfigOptionEnum< InfillPattern >, fill_pattern))((ConfigOptionEnum< FuzzySkinType >
infill_extrusion_width((ConfigOptionInt, infill_every_layers))((ConfigOptionFloatOrPercent
PrintObjectConfig
Definition PrintConfig.hpp:840
@ frInfill
Definition Flow.hpp:19
PrintRegionConfig
Definition PrintConfig.hpp:840

References Slic3r::PrintObjectRegions::all_regions, Slic3r::Flow::auto_extrusion_width(), Slic3r::PrintObject::config(), Slic3r::Print::config(), Slic3r::fill_density(), Slic3r::frInfill, generateInitialInternalOverhangs(), generateTrees(), m_infill_extrusion_width, M_PI, m_prune_length, m_straightening_max_distance, m_supporting_radius, m_wall_supporting_radius, Slic3r::PrintObjectBaseWithState< PrintType, PrintObjectStepEnumType, COUNT >::print(), Slic3r::PrintObjectConfig, Slic3r::PrintRegionConfig, and Slic3r::PrintObject::shared_regions().

+ Here is the call graph for this function:

Member Function Documentation

◆ generateInitialInternalOverhangs()

void Slic3r::FillLightning::Generator::generateInitialInternalOverhangs ( const PrintObject print_object,
const std::function< void()> &  throw_on_cancel_callback 
)
protected

Calculate the overhangs above the infill areas that need to be supported by infill.

Normally, overhangs are only generated for the outside of the model and only when support is generated. For this pattern, we also need to generate overhang areas for the inside of the model.

56{
57 m_overhang_per_layer.resize(print_object.layers().size());
58
59 Polygons infill_area_above;
60 // 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.
61 for (int layer_nr = int(print_object.layers().size()) - 1; layer_nr >= 0; --layer_nr) {
62 throw_on_cancel_callback();
63 Polygons infill_area_here;
64 for (const LayerRegion* layerm : print_object.get_layer(layer_nr)->regions())
65 for (const Surface& surface : layerm->fill_surfaces())
66 if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
67 append(infill_area_here, to_polygons(surface.expolygon));
68
69 infill_area_here = union_(infill_area_here);
70 // Remove the part of the infill area that is already supported by the walls.
71 Polygons overhang = diff(offset(infill_area_here, -float(m_wall_supporting_radius)), infill_area_above);
72 // Filter out unprintable polygons and near degenerated polygons (three almost collinear points and so).
73 overhang = opening(overhang, float(SCALED_EPSILON), float(SCALED_EPSILON));
74
75 m_overhang_per_layer[layer_nr] = overhang;
76 infill_area_above = std::move(infill_area_here);
77 }
78}
std::vector< Polygons > m_overhang_per_layer
Definition Generator.hpp:118
#define const
Definition getopt.c:38
if(!(yy_init))
Definition lexer.c:1190
#define SCALED_EPSILON
Definition libslic3r.h:71
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:15
Slic3r::Polygons union_(const Slic3r::Polygons &subject)
Definition ClipperUtils.cpp:704
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:416
Polygons to_polygons(const ExPolygon &src)
Definition ExPolygon.hpp:281
@ stInternal
Definition Surface.hpp:17
@ stInternalVoid
Definition Surface.hpp:24
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:110
Slic3r::Polygons opening(const Slic3r::Polygons &polygons, const float delta1, const float delta2, ClipperLib::JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:608
Slic3r::Polygons diff(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:672

References Slic3r::append(), Slic3r::diff(), Slic3r::PrintObject::get_layer(), Slic3r::PrintObject::layers(), m_overhang_per_layer, m_wall_supporting_radius, Slic3r::offset(), Slic3r::opening(), Slic3r::Layer::regions(), SCALED_EPSILON, Slic3r::stInternal, Slic3r::stInternalVoid, Slic3r::to_polygons(), and Slic3r::union_().

Referenced by Generator().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateTrees()

void Slic3r::FillLightning::Generator::generateTrees ( const PrintObject print_object,
const std::function< void()> &  throw_on_cancel_callback 
)
protected

Calculate the tree structure of all layers.

87{
88 m_lightning_layers.resize(print_object.layers().size());
89
90 std::vector<Polygons> infill_outlines(print_object.layers().size(), Polygons());
91
92 // For-each layer from top to bottom:
93 for (int layer_id = int(print_object.layers().size()) - 1; layer_id >= 0; layer_id--) {
94 throw_on_cancel_callback();
95 for (const LayerRegion *layerm : print_object.get_layer(layer_id)->regions())
96 for (const Surface &surface : layerm->fill_surfaces())
97 if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
98 append(infill_outlines[layer_id], to_polygons(surface.expolygon));
99
100 infill_outlines[layer_id] = union_(infill_outlines[layer_id]);
101 }
102
103 // For various operations its beneficial to quickly locate nearby features on the polygon:
104 const size_t top_layer_id = print_object.layers().size() - 1;
105 EdgeGrid::Grid outlines_locator(get_extents(infill_outlines[top_layer_id]).inflated(SCALED_EPSILON));
106 outlines_locator.create(infill_outlines[top_layer_id], locator_cell_size);
107
108 // For-each layer from top to bottom:
109 for (int layer_id = int(top_layer_id); layer_id >= 0; layer_id--) {
110 throw_on_cancel_callback();
111 Layer &current_lightning_layer = m_lightning_layers[layer_id];
112 const Polygons &current_outlines = infill_outlines[layer_id];
113 const BoundingBox &current_outlines_bbox = get_extents(current_outlines);
114
115 // register all trees propagated from the previous layer as to-be-reconnected
116 std::vector<NodeSPtr> to_be_reconnected_tree_roots = current_lightning_layer.tree_roots;
117
118 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);
119 current_lightning_layer.reconnectRoots(to_be_reconnected_tree_roots, current_outlines, current_outlines_bbox, outlines_locator, m_supporting_radius, m_wall_supporting_radius);
120
121 // Initialize trees for next lower layer from the current one.
122 if (layer_id == 0)
123 return;
124
125 const Polygons &below_outlines = infill_outlines[layer_id - 1];
126 BoundingBox below_outlines_bbox = get_extents(below_outlines).inflated(SCALED_EPSILON);
127 if (const BoundingBox &outlines_locator_bbox = outlines_locator.bbox(); outlines_locator_bbox.defined)
128 below_outlines_bbox.merge(outlines_locator_bbox);
129
130 if (!current_lightning_layer.tree_roots.empty())
131 below_outlines_bbox.merge(get_extents(current_lightning_layer.tree_roots).inflated(SCALED_EPSILON));
132
133 outlines_locator.set_bbox(below_outlines_bbox);
134 outlines_locator.create(below_outlines, locator_cell_size);
135
136 std::vector<NodeSPtr>& lower_trees = m_lightning_layers[layer_id - 1].tree_roots;
137 for (auto& tree : current_lightning_layer.tree_roots)
138 tree->propagateToNextLayer(lower_trees, below_outlines, outlines_locator, m_prune_length, m_straightening_max_distance, locator_cell_size / 2);
139 }
140}
void merge(const PointType &point)
Definition BoundingBox.cpp:62
BoundingBox inflated(coordf_t delta) const
Definition BoundingBox.hpp:197
std::vector< Layer > m_lightning_layers
Definition Generator.hpp:125
BoundingBox get_extents(const NodeSPtr &root_node)
Definition TreeNode.hpp:284
constexpr auto locator_cell_size
Definition TreeNode.hpp:21

References Slic3r::append(), Slic3r::EdgeGrid::Grid::bbox(), Slic3r::EdgeGrid::Grid::create(), Slic3r::FillLightning::Layer::generateNewTrees(), Slic3r::FillLightning::get_extents(), Slic3r::PrintObject::get_layer(), Slic3r::BoundingBox::inflated(), Slic3r::PrintObject::layers(), Slic3r::FillLightning::locator_cell_size, m_lightning_layers, m_overhang_per_layer, m_prune_length, m_straightening_max_distance, m_supporting_radius, m_wall_supporting_radius, Slic3r::BoundingBoxBase< PointType, APointsType >::merge(), Slic3r::FillLightning::Layer::reconnectRoots(), Slic3r::Layer::regions(), SCALED_EPSILON, Slic3r::EdgeGrid::Grid::set_bbox(), Slic3r::stInternal, Slic3r::stInternalVoid, Slic3r::to_polygons(), Slic3r::FillLightning::Layer::tree_roots, and Slic3r::union_().

Referenced by Generator().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getTreesForLayer()

const Layer & Slic3r::FillLightning::Generator::getTreesForLayer ( const size_t &  layer_id) const

Get a tree of paths generated for a certain layer of the mesh.

This tree represents the paths that must be traced to print the infill.

Parameters
layer_idThe layer number to get the path tree for. This is within the range of layers of the mesh (not the global layer numbers).
Returns
A tree structure representing paths to print to create the Lightning Infill pattern.
81{
82 assert(layer_id < m_lightning_layers.size());
83 return m_lightning_layers[layer_id];
84}

References m_lightning_layers.

Referenced by Slic3r::FillLightning::Filler::_fill_surface_single().

+ Here is the caller graph for this function:

◆ infilll_extrusion_width()

float Slic3r::FillLightning::Generator::infilll_extrusion_width ( ) const
inline

Member Data Documentation

◆ m_infill_extrusion_width

float Slic3r::FillLightning::Generator::m_infill_extrusion_width
protected

◆ m_lightning_layers

std::vector<Layer> Slic3r::FillLightning::Generator::m_lightning_layers
protected

For each layer, the generated lightning paths.

This is generated by generateTrees.

Referenced by generateTrees(), and getTreesForLayer().

◆ m_overhang_per_layer

std::vector<Polygons> Slic3r::FillLightning::Generator::m_overhang_per_layer
protected

For each layer, the overhang that needs to be supported by the pattern.

This is generated by generateInitialInternalOverhangs.

Referenced by generateInitialInternalOverhangs(), and generateTrees().

◆ m_prune_length

coord_t Slic3r::FillLightning::Generator::m_prune_length
protected

How far each piece of infill can support other infill in the layer above.

This may be different than supporting_radius, because the infill is printed with one end floating in mid-air. This endpoint will sag more, so an infill line may need to be supported more than a skin line.

Referenced by Generator(), and generateTrees().

◆ m_straightening_max_distance

coord_t Slic3r::FillLightning::Generator::m_straightening_max_distance
protected

How far a line may be shifted in order to straighten the line out.

Straightening the line reduces material and time usage and reduces accelerations needed to print the pattern. However it makes the infill weak if lines are partially suspended next to the line on the previous layer.

Referenced by Generator(), and generateTrees().

◆ m_supporting_radius

coord_t Slic3r::FillLightning::Generator::m_supporting_radius
protected

How far each piece of infill can support skin in the layer above.

Referenced by Generator(), and generateTrees().

◆ m_wall_supporting_radius

coord_t Slic3r::FillLightning::Generator::m_wall_supporting_radius
protected

How far a wall can support the wall above it. If a wall completely supports the wall above it, no infill needs to support that.

This is similar to the overhang distance calculated for support. It is determined by the lightning_infill_overhang_angle setting.

Referenced by Generator(), generateInitialInternalOverhangs(), and generateTrees().


The documentation for this class was generated from the following files: