2023-06-10 10:14:12 +08:00
# ifndef slic3r_Layer_hpp_
# define slic3r_Layer_hpp_
# include "Line.hpp"
# include "libslic3r.h"
# include "BoundingBox.hpp"
# include "Flow.hpp"
# include "SurfaceCollection.hpp"
# include "ExtrusionEntityCollection.hpp"
2024-03-30 10:22:25 +08:00
# include "LayerRegion.hpp"
2023-06-10 10:14:12 +08:00
# include <boost/container/small_vector.hpp>
namespace Slic3r {
class ExPolygon ;
using ExPolygons = std : : vector < ExPolygon > ;
class Layer ;
using LayerPtrs = std : : vector < Layer * > ;
class LayerRegion ;
using LayerRegionPtrs = std : : vector < LayerRegion * > ;
class PrintRegion ;
class PrintObject ;
namespace FillAdaptive {
struct Octree ;
}
namespace FillLightning {
class Generator ;
} ;
// Range of extrusions, referencing the source region by an index.
class LayerExtrusionRange : public ExtrusionRange
{
public :
LayerExtrusionRange ( uint32_t iregion , ExtrusionRange extrusion_range ) : m_region ( iregion ) , ExtrusionRange ( extrusion_range ) { }
LayerExtrusionRange ( ) = default ;
// Index of LayerRegion in Layer.
uint32_t region ( ) const { return m_region ; } ;
private :
// Index of LayerRegion in Layer.
uint32_t m_region { 0 } ;
} ;
// One LayerIsland may be filled with solid fill, sparse fill, top / bottom fill.
static constexpr const size_t LayerExtrusionRangesStaticSize = 3 ;
using LayerExtrusionRanges =
# ifdef NDEBUG
// To reduce memory allocation in release mode.
boost : : container : : small_vector < LayerExtrusionRange , LayerExtrusionRangesStaticSize > ;
# else // NDEBUG
// To ease debugging.
std : : vector < LayerExtrusionRange > ;
# endif // NDEBUG
// LayerSlice contains one or more LayerIsland objects,
// each LayerIsland containing a set of perimeter extrusions extruded with one particular PrintRegionConfig parameters
// and one or multiple
struct LayerIsland
{
private :
friend class Layer ;
static constexpr const uint32_t fill_region_composite_id = std : : numeric_limits < uint32_t > : : max ( ) ;
public :
// Perimeter extrusions in LayerRegion belonging to this island.
LayerExtrusionRange perimeters ;
// Thin fills of the same region as perimeters. Generated by classic perimeter generator, while Arachne puts them into perimeters.
ExtrusionRange thin_fills ;
// Infill + gapfill extrusions in LayerRegion belonging to this island.
LayerExtrusionRanges fills ;
// Region that is to be filled with the fills above (thin fills, regular fills).
// Pointing to either LayerRegion::fill_expolygons() or LayerRegion::fill_expolygons_composite()
// based on this->fill_expolygons_composite() flag.
ExPolygonRange fill_expolygons ;
// Index of LayerRegion with LayerRegion::fill_expolygons() if not fill_expolygons_composite().
uint32_t fill_region_id ;
bool fill_expolygons_composite ( ) const { return this - > fill_region_id = = fill_region_composite_id ; }
// Centroid of this island used for path planning.
// Point centroid;
bool has_extrusions ( ) const { return ! this - > perimeters . empty ( ) | | ! this - > fills . empty ( ) ; }
void add_fill_range ( const LayerExtrusionRange & new_fill_range ) {
// Compress ranges.
if ( ! this - > fills . empty ( ) & & this - > fills . back ( ) . region ( ) = = new_fill_range . region ( ) & & * this - > fills . back ( ) . end ( ) = = * new_fill_range . begin ( ) )
this - > fills . back ( ) = { new_fill_range . region ( ) , { * this - > fills . back ( ) . begin ( ) , * new_fill_range . end ( ) } } ;
else
this - > fills . push_back ( new_fill_range ) ;
}
} ;
static constexpr const size_t LayerIslandsStaticSize = 1 ;
using LayerIslands =
# ifdef NDEBUG
// To reduce memory allocation in release mode.
boost : : container : : small_vector < LayerIsland , LayerIslandsStaticSize > ;
# else // NDEBUG
// To ease debugging.
std : : vector < LayerIsland > ;
# endif // NDEBUG
// One connected island of a layer. LayerSlice may consist of one or more LayerIslands.
struct LayerSlice
{
struct Link {
int32_t slice_idx ;
float area ;
} ;
static constexpr const size_t LinksStaticSize = 4 ;
using Links =
# ifdef NDEBUG
// To reduce memory allocation in release mode.
boost : : container : : small_vector < Link , LinksStaticSize > ;
# else // NDEBUG
// To ease debugging.
std : : vector < Link > ;
# endif // NDEBUG
BoundingBox bbox ;
Links overlaps_above ;
Links overlaps_below ;
// One island for each region or region set that generates its own perimeters.
// For multi-material prints or prints with regions of different perimeter parameters,
// a LayerSlice may be split into multiple LayerIslands.
// For most prints there will be just one island.
LayerIslands islands ;
bool has_extrusions ( ) const { for ( const LayerIsland & island : islands ) if ( island . has_extrusions ( ) ) return true ; return false ; }
} ;
using LayerSlices = std : : vector < LayerSlice > ;
class Layer
{
public :
// Sequential index of this layer in PrintObject::m_layers, offsetted by the number of raft layers.
size_t id ( ) const { return m_id ; }
void set_id ( size_t id ) { m_id = id ; }
PrintObject * object ( ) { return m_object ; }
const PrintObject * object ( ) const { return m_object ; }
Layer * upper_layer ;
Layer * lower_layer ;
// bool slicing_errors;
coordf_t slice_z ; // Z used for slicing in unscaled coordinates
coordf_t print_z ; // Z used for printing in unscaled coordinates
coordf_t height ; // layer height in unscaled coordinates
coordf_t bottom_z ( ) const { return this - > print_z - this - > height ; }
//Extrusions estimated to be seriously malformed, estimated during "Estimating curled extrusions" step. These lines should be avoided during fast travels.
CurledLines curled_lines ;
// Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry
// (with possibly differing extruder ID and slicing parameters) and merged.
// For the first layer, if the Elephant foot compensation is applied, this lslice is uncompensated, therefore
// it includes the Elephant foot effect, thus it corresponds to the shape of the printed 1st layer.
// These lslices aka islands are chained by the shortest traverse distance and this traversal
// order will be applied by the G-code generator to the extrusions fitting into these lslices.
// These lslices are also used to detect overhangs and overlaps between successive layers, therefore it is important
// that the 1st lslice is not compensated by the Elephant foot compensation algorithm.
ExPolygons lslices ;
std : : vector < size_t > lslice_indices_sorted_by_print_order ;
LayerSlices lslices_ex ;
size_t region_count ( ) const { return m_regions . size ( ) ; }
const LayerRegion * get_region ( int idx ) const { return m_regions [ idx ] ; }
LayerRegion * get_region ( int idx ) { return m_regions [ idx ] ; }
LayerRegion * add_region ( const PrintRegion * print_region ) ;
const LayerRegionPtrs & regions ( ) const { return m_regions ; }
// Test whether whether there are any slices assigned to this layer.
bool empty ( ) const ;
void make_slices ( ) ;
// After creating the slices on all layers, chain the islands overlapping in Z.
static void build_up_down_graph ( Layer & below , Layer & above ) ;
// Backup and restore raw sliced regions if needed.
//FIXME Review whether not to simplify the code by keeping the raw_slices all the time.
void backup_untyped_slices ( ) ;
void restore_untyped_slices ( ) ;
// To improve robustness of detect_surfaces_type() when reslicing (working with typed slices), see GH issue #7442.
void restore_untyped_slices_no_extra_perimeters ( ) ;
// Slices merged into islands, to be used by the elephant foot compensation to trim the individual surfaces with the shrunk merged slices.
ExPolygons merged ( float offset ) const ;
template < class T > bool any_internal_region_slice_contains ( const T & item ) const {
for ( const LayerRegion * layerm : m_regions ) if ( layerm - > slices ( ) . any_internal_contains ( item ) ) return true ;
return false ;
}
template < class T > bool any_bottom_region_slice_contains ( const T & item ) const {
for ( const LayerRegion * layerm : m_regions ) if ( layerm - > slices ( ) . any_bottom_contains ( item ) ) return true ;
return false ;
}
void make_perimeters ( ) ;
void make_fills ( FillAdaptive : : Octree * adaptive_fill_octree ,
FillAdaptive : : Octree * support_fill_octree ,
FillLightning : : Generator * lightning_generator ) ;
Polylines generate_sparse_infill_polylines_for_anchoring ( FillAdaptive : : Octree * adaptive_fill_octree ,
FillAdaptive : : Octree * support_fill_octree ,
FillLightning : : Generator * lightning_generator ) const ;
void make_ironing ( ) ;
void export_region_slices_to_svg ( const char * path ) const ;
void export_region_fill_surfaces_to_svg ( const char * path ) const ;
// Export to "out/LayerRegion-name-%d.svg" with an increasing index with every export.
void export_region_slices_to_svg_debug ( const char * name ) const ;
void export_region_fill_surfaces_to_svg_debug ( const char * name ) const ;
// Is there any valid extrusion assigned to this LayerRegion?
virtual bool has_extrusions ( ) const { for ( auto layerm : m_regions ) if ( layerm - > has_extrusions ( ) ) return true ; return false ; }
// virtual bool has_extrusions() const { for (const LayerSlice &lslice : lslices_ex) if (lslice.has_extrusions()) return true; return false; }
2024-03-08 09:11:53 +08:00
//w21
2024-03-16 10:51:48 +08:00
void variable_width_gap ( const ThickPolylines & polylines , ExtrusionRole role , const Flow & flow , std : : vector < ExtrusionEntity * > & out , const float filter_gap_infill_value ) ;
2024-03-08 09:11:53 +08:00
ExtrusionPaths thick_polyline_to_extrusion_paths ( const ThickPolyline & thick_polyline , ExtrusionRole role , const Flow & flow , const float tolerance ) ;
2023-06-10 10:14:12 +08:00
protected :
friend class PrintObject ;
friend std : : vector < Layer * > new_layers ( PrintObject * , const std : : vector < coordf_t > & ) ;
friend std : : string fix_slicing_errors ( LayerPtrs & , const std : : function < void ( ) > & ) ;
Layer ( size_t id , PrintObject * object , coordf_t height , coordf_t print_z , coordf_t slice_z ) :
upper_layer ( nullptr ) , lower_layer ( nullptr ) ,
//slicing_errors(false),
slice_z ( slice_z ) , print_z ( print_z ) , height ( height ) ,
m_id ( id ) , m_object ( object ) { }
virtual ~ Layer ( ) ;
// Clear fill extrusions, remove them from layer islands.
void clear_fills ( ) ;
private :
void sort_perimeters_into_islands (
// Slices for which perimeters and fill_expolygons were just created.
// The slices may have been created by merging multiple source slices with the same perimeter parameters.
const SurfaceCollection & slices ,
// Region where the perimeters, gap fills and fill expolygons are stored.
const uint32_t region_id ,
// Perimeters and gap fills produced by the perimeter generator for the slices,
// sorted by the source slices.
const std : : vector < std : : pair < ExtrusionRange , ExtrusionRange > > & perimeter_and_gapfill_ranges ,
// Fill expolygons produced for all source slices above.
ExPolygons & & fill_expolygons ,
// Fill expolygon ranges sorted by the source slices.
const std : : vector < ExPolygonRange > & fill_expolygons_ranges ,
// If the current layer consists of multiple regions, then the fill_expolygons above are split by the source LayerRegion surfaces.
const std : : vector < uint32_t > & layer_region_ids ) ;
// Sequential index of layer, 0-based, offsetted by number of raft layers.
size_t m_id ;
PrintObject * m_object ;
LayerRegionPtrs m_regions ;
} ;
class SupportLayer : public Layer
{
public :
// Polygons covered by the supports: base, interface and contact areas.
// Used to suppress retraction if moving for a support extrusion over these support_islands.
ExPolygons support_islands ;
// Slightly inflated bounding boxes of the above, for faster intersection query.
BoundingBoxes support_islands_bboxes ;
// Extrusion paths for the support base and for the support interface and contacts.
ExtrusionEntityCollection support_fills ;
// Is there any valid extrusion assigned to this LayerRegion?
virtual bool has_extrusions ( ) const { return ! support_fills . empty ( ) ; }
// Zero based index of an interface layer, used for alternating direction of interface / contact layers.
size_t interface_id ( ) const { return m_interface_id ; }
protected :
friend class PrintObject ;
// The constructor has been made public to be able to insert additional support layers for the skirt or a wipe tower
// between the raft and the object first layer.
SupportLayer ( size_t id , size_t interface_id , PrintObject * object , coordf_t height , coordf_t print_z , coordf_t slice_z ) :
Layer ( id , object , height , print_z , slice_z ) , m_interface_id ( interface_id ) { }
virtual ~ SupportLayer ( ) = default ;
size_t m_interface_id ;
} ;
template < typename LayerContainer >
inline std : : vector < float > zs_from_layers ( const LayerContainer & layers )
{
std : : vector < float > zs ;
zs . reserve ( layers . size ( ) ) ;
for ( const Layer * l : layers )
zs . emplace_back ( ( float ) l - > slice_z ) ;
return zs ;
}
extern BoundingBox get_extents ( const LayerRegion & layer_region ) ;
extern BoundingBox get_extents ( const LayerRegionPtrs & layer_regions ) ;
}
# endif