OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::TreeSupportData Class Reference

Lazily generates tree guidance volumes. More...

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Support/TreeSupport.hpp>

Collaboration diagram for Slic3r::TreeSupportData:

Classes

struct  RadiusLayerPair
 Convenience typedef for the keys to the caches. More...
struct  RadiusLayerPairEquality
struct  RadiusLayerPairHash

Public Member Functions

 TreeSupportData ()=default
 TreeSupportData (const PrintObject &object, coordf_t xy_distance, coordf_t radius_sample_resolution)
 Construct the TreeSupportData object.
 ~TreeSupportData ()
 TreeSupportData (TreeSupportData &&)=delete
TreeSupportData & operator= (TreeSupportData &&)=delete
 TreeSupportData (const TreeSupportData &)=delete
TreeSupportData & operator= (const TreeSupportData &)=delete
const ExPolygons & get_collision (coordf_t radius, size_t layer_idx) const
 Creates the areas that have to be avoided by the tree's branches.
const ExPolygons & get_avoidance (coordf_t radius, size_t layer_idx, int recursions=0) const
 Creates the areas that have to be avoided by the tree's branches in order to reach the build plate.
Polygons get_contours (size_t layer_nr) const
Polygons get_contours_with_holes (size_t layer_nr) const
SupportNode * create_node (const Point position, const int distance_to_top, const int obj_layer_nr, const int support_roof_layers_below, const bool to_buildplate, SupportNode *parent, coordf_t print_z_, coordf_t height_, coordf_t dist_mm_to_top_=0, coordf_t radius_=0)
void clear_nodes ()

Public Attributes

std::vector< LayerHeightData > layer_heights
std::vector< std::unique_ptr< SupportNode > > contact_nodes
bool is_slim = false
coordf_t m_xy_distance
 The required clearance between the model and the tree branches.
double branch_scale_factor = 1.0
coordf_t m_radius_sample_resolution
 Sample resolution for radius values.
std::vector< ExPolygons > m_layer_outlines
 Storage for layer outlines of the meshes.
std::vector< ExPolygons > m_layer_outlines_below
std::vector< double > m_max_move_distances
tbb::concurrent_unordered_map< RadiusLayerPair, ExPolygons, RadiusLayerPairHash, RadiusLayerPairEquality > m_collision_cache
 Caches for the collision, avoidance and internal model polygons at given radius and layer indices.
tbb::concurrent_unordered_map< RadiusLayerPair, ExPolygons, RadiusLayerPairHash, RadiusLayerPairEquality > m_avoidance_cache
friend TreeSupport

Private Member Functions

coordf_t ceil_radius (coordf_t radius) const
 Round radius upwards to a multiple of m_radius_sample_resolution.
const ExPolygons & calculate_collision (const RadiusLayerPair &key) const
 Calculate the collision areas at the radius and layer indicated by key.
const ExPolygons & calculate_avoidance (const RadiusLayerPair &key) const
 Calculate the avoidance areas at the radius and layer indicated by key.

Private Attributes

tbb::spin_mutex m_mutex

Detailed Description

Lazily generates tree guidance volumes.

Warning
This class is not currently thread-safe and should not be accessed in OpenMP blocks

Class Documentation

◆ Slic3r::TreeSupportData::RadiusLayerPair

struct Slic3r::TreeSupportData::RadiusLayerPair

Convenience typedef for the keys to the caches.

Class Members
size_t layer_nr
coordf_t radius
int recursions

Constructor & Destructor Documentation

◆ TreeSupportData() [1/4]

Slic3r::TreeSupportData::TreeSupportData ( )
default

Referenced by TreeSupportData(), TreeSupportData(), TreeSupportData(), operator=(), and operator=().

Here is the caller graph for this function:

◆ TreeSupportData() [2/4]

Slic3r::TreeSupportData::TreeSupportData ( const PrintObject & object,
coordf_t xy_distance,
coordf_t radius_sample_resolution )

Construct the TreeSupportData object.

Parameters
xy_distanceThe required clearance between the model and the tree branches.
radius_sample_resolutionSample size used to round requested node radii.
3916 : m_xy_distance(xy_distance), m_radius_sample_resolution(radius_sample_resolution)
3917{
3918 branch_scale_factor = tan(object.config().tree_support_branch_angle.value * M_PI / 180.);
3919 clear_nodes();
3920 m_max_move_distances.resize(object.layers().size(), 0);
3921 for (std::size_t layer_nr = 0; layer_nr < object.layers().size(); ++layer_nr)
3922 {
3923 const Layer* layer = object.get_layer(layer_nr);
3924 m_max_move_distances[layer_nr] = layer->height * branch_scale_factor;
3925 m_layer_outlines.push_back(ExPolygons());
3926 ExPolygons& outline = m_layer_outlines.back();
3927 for (const ExPolygon& poly : layer->lslices) {
3928 poly.simplify(scale_(m_radius_sample_resolution), &outline);
3929 }
3930
3931 // The belt surface is deliberately NOT part of the outlines. The outlines
3932 // feed the collision and avoidance maps, and a node descending onto an
3933 // obstacle is pushed out of it: with the belt as an obstacle the nodes slid
3934 // down the tilted surface, ahead of the part, instead of landing on it. The
3935 // belt is where a branch ENDS: drop_nodes() stops a node once its whole
3936 // circle is in the belt (belt_node_landed()) and draw_circles() clips every
3937 // layer's circles to the belt plane, so the branch tapers to a tip on it.
3938
3939 if (layer_nr == 0)
3940 m_layer_outlines_below.push_back(outline);
3941 else
3942 m_layer_outlines_below.push_back(union_ex(m_layer_outlines_below.end()[-1], outline));
3943 }
3944}
#define M_PI
Definition ExtrusionSimulator.cpp:31
coordf_t m_xy_distance
The required clearance between the model and the tree branches.
Definition TreeSupport.hpp:317
double branch_scale_factor
Definition TreeSupport.hpp:319
std::vector< ExPolygons > m_layer_outlines
Storage for layer outlines of the meshes.
Definition TreeSupport.hpp:333
std::vector< double > m_max_move_distances
Definition TreeSupport.hpp:338
std::vector< ExPolygons > m_layer_outlines_below
Definition TreeSupport.hpp:336
void clear_nodes()
Definition TreeSupport.cpp:4002
coordf_t m_radius_sample_resolution
Sample resolution for radius values.
Definition TreeSupport.hpp:328
#define scale_(val)
Definition libslic3r.h:106
void poly(std::vector< std::pair< Vec2d, Vec2d > > &out, std::initializer_list< Vec2d > p)
Definition DesignSketchTool.cpp:7751
std::vector< ExPolygon > ExPolygons
Definition ExPolygon.hpp:20
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, PolyFillType fill_type)
Definition ClipperUtils.cpp:1011

References TreeSupportData(), branch_scale_factor, clear_nodes(), Slic3r::Layer::height, Slic3r::Layer::lslices, m_layer_outlines, m_layer_outlines_below, m_max_move_distances, M_PI, m_radius_sample_resolution, m_xy_distance, scale_, and Slic3r::union_ex().

Here is the call graph for this function:

◆ ~TreeSupportData()

Slic3r::TreeSupportData::~TreeSupportData ( )
inline
216 {
217 clear_nodes();
218 }

References clear_nodes().

Here is the call graph for this function:

◆ TreeSupportData() [3/4]

Slic3r::TreeSupportData::TreeSupportData ( TreeSupportData && )
delete

References TreeSupportData().

Here is the call graph for this function:

◆ TreeSupportData() [4/4]

Slic3r::TreeSupportData::TreeSupportData ( const TreeSupportData & )
delete

References TreeSupportData().

Here is the call graph for this function:

Member Function Documentation

◆ calculate_avoidance()

const ExPolygons & Slic3r::TreeSupportData::calculate_avoidance ( const RadiusLayerPair & key) const
private

Calculate the avoidance areas at the radius and layer indicated by key.

Parameters
keyThe radius and layer of the node of interest
4032{
4033 const auto &radius = key.radius;
4034 const auto &layer_nr = key.layer_nr;
4035 ExPolygons avoidance_areas;
4036 if (layer_nr > 0) {
4037 // Avoidance for a given layer depends on all layers beneath it so could have very deep recursion depths if
4038 // called at high layer heights. We can limit the reqursion depth to N by checking if the layer N
4039 // below the current one exists and if not, forcing the calculation of that layer. This may cause another recursion
4040 // if the layer at 2N below the current one but we won't exceed our limit unless there are N*N uncalculated layers
4041 // below our current one.
4042 constexpr auto max_recursion_depth = 100;
4043 // Check if we would exceed the recursion limit by trying to process this layer
4044 if (layer_nr >= max_recursion_depth && m_avoidance_cache.find({radius, layer_nr - max_recursion_depth}) == m_avoidance_cache.end()) {
4045 // Force the calculation of the layer `max_recursion_depth` below our current one, ignoring the result.
4046 get_avoidance(radius, layer_nr - max_recursion_depth);
4047 }
4048
4049 avoidance_areas = offset_ex(get_avoidance(radius, layer_nr - 1), scale_(-m_max_move_distances[layer_nr-1]));
4050 }
4051 const ExPolygons &collision = get_collision(radius, layer_nr);
4052 avoidance_areas.insert(avoidance_areas.end(), collision.begin(), collision.end());
4053 avoidance_areas = union_ex(avoidance_areas);
4054 auto ret = m_avoidance_cache.insert({key, std::move(avoidance_areas)});
4055 //assert(ret.second);
4056 return ret.first->second;
4057}
tbb::concurrent_unordered_map< RadiusLayerPair, ExPolygons, RadiusLayerPairHash, RadiusLayerPairEquality > m_avoidance_cache
Definition TreeSupport.hpp:353
const ExPolygons & get_avoidance(coordf_t radius, size_t layer_idx, int recursions=0) const
Creates the areas that have to be avoided by the tree's branches in order to reach the build plate.
Definition TreeSupport.cpp:3957
const ExPolygons & get_collision(coordf_t radius, size_t layer_idx) const
Creates the areas that have to be avoided by the tree's branches.
Definition TreeSupport.cpp:3946
Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:605

References get_avoidance(), get_collision(), Slic3r::TreeSupportData::RadiusLayerPair::layer_nr, m_avoidance_cache, m_max_move_distances, Slic3r::offset_ex(), Slic3r::TreeSupportData::RadiusLayerPair::radius, scale_, and Slic3r::union_ex().

Referenced by get_avoidance().

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

◆ calculate_collision()

const ExPolygons & Slic3r::TreeSupportData::calculate_collision ( const RadiusLayerPair & key) const
private

Calculate the collision areas at the radius and layer indicated by key.

Parameters
keyThe radius and layer of the node of interest
4021{
4022 assert(key.layer_nr < m_layer_outlines.size());
4023
4024 ExPolygons collision_areas = offset_ex(m_layer_outlines[key.layer_nr], scale_(key.radius+m_xy_distance));
4025 collision_areas = expolygons_simplify(collision_areas, scale_(m_radius_sample_resolution));
4026 // collision_areas.emplace_back(m_machine_border);
4027 const auto ret = m_collision_cache.insert({ key, std::move(collision_areas) });
4028 return ret.first->second;
4029}
tbb::concurrent_unordered_map< RadiusLayerPair, ExPolygons, RadiusLayerPairHash, RadiusLayerPairEquality > m_collision_cache
Caches for the collision, avoidance and internal model polygons at given radius and layer indices.
Definition TreeSupport.hpp:352
ExPolygons expolygons_simplify(const ExPolygons &expolys, double tolerance)
Definition ExPolygon.hpp:477

References Slic3r::expolygons_simplify(), Slic3r::TreeSupportData::RadiusLayerPair::layer_nr, m_collision_cache, m_layer_outlines, m_radius_sample_resolution, m_xy_distance, Slic3r::offset_ex(), Slic3r::TreeSupportData::RadiusLayerPair::radius, and scale_.

Referenced by get_collision().

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

◆ ceil_radius()

coordf_t Slic3r::TreeSupportData::ceil_radius ( coordf_t radius) const
private

Round radius upwards to a multiple of m_radius_sample_resolution.

Parameters
radiusThe radius of the node of interest
4009{
4010 size_t factor = (size_t)(radius / m_radius_sample_resolution);
4011 coordf_t remains = radius - m_radius_sample_resolution * factor;
4012 if (remains > EPSILON) {
4013 return radius + m_radius_sample_resolution - remains;
4014 }
4015 else {
4016 return radius;
4017 }
4018}
#define EPSILON
Definition ColorUtils.cpp:64
double coordf_t
Definition GUI_ObjectList.hpp:46

References EPSILON, and m_radius_sample_resolution.

Referenced by get_avoidance(), and get_collision().

Here is the caller graph for this function:

◆ clear_nodes()

void Slic3r::TreeSupportData::clear_nodes ( )
4003{
4004 tbb::spin_mutex::scoped_lock guard(m_mutex);
4005 contact_nodes.clear();
4006}
tbb::spin_mutex m_mutex
Definition TreeSupport.hpp:310
std::vector< std::unique_ptr< SupportNode > > contact_nodes
Definition TreeSupport.hpp:263

References contact_nodes, and m_mutex.

Referenced by TreeSupportData(), and ~TreeSupportData().

Here is the caller graph for this function:

◆ create_node()

SupportNode * Slic3r::TreeSupportData::create_node ( const Point position,
const int distance_to_top,
const int obj_layer_nr,
const int support_roof_layers_below,
const bool to_buildplate,
SupportNode * parent,
coordf_t print_z_,
coordf_t height_,
coordf_t dist_mm_to_top_ = 0,
coordf_t radius_ = 0 )
3990{
3991 // this function may be called from multiple threads, need to lock
3992 m_mutex.lock();
3993 std::unique_ptr<SupportNode> node = std::make_unique<SupportNode>(position, distance_to_top, obj_layer_nr, support_roof_layers_below, to_buildplate, parent, print_z_, height_, dist_mm_to_top_, radius_);
3994 SupportNode* raw_ptr = node.get();
3995 contact_nodes.emplace_back(std::move(node));
3996 m_mutex.unlock();
3997 if (parent)
3998 raw_ptr->movement = position - parent->position;
3999 return raw_ptr;
4000}

References contact_nodes, m_mutex, Slic3r::SupportNode::movement, and Slic3r::SupportNode::position.

◆ get_avoidance()

const ExPolygons & Slic3r::TreeSupportData::get_avoidance ( coordf_t radius,
size_t layer_idx,
int recursions = 0 ) const

Creates the areas that have to be avoided by the tree's branches in order to reach the build plate.

The result is a 2D area that would cause nodes of radius radius to collide with the model or be unable to reach the build platform.

The input collision areas are inset by the maximum move distance and propagated upwards.

Parameters
radiusThe radius of the node of interest
layerThe layer of interest
Returns
Polygons object
3958{
3959 profiler.tic();
3960 radius = ceil_radius(radius);
3961 RadiusLayerPair key{radius, layer_nr, recursions };
3962 const auto it = m_avoidance_cache.find(key);
3963 const ExPolygons& avoidance = it != m_avoidance_cache.end() ? it->second : calculate_avoidance(key);
3964
3966 return avoidance;
3967}
coordf_t ceil_radius(coordf_t radius) const
Round radius upwards to a multiple of m_radius_sample_resolution.
Definition TreeSupport.cpp:4008
const ExPolygons & calculate_avoidance(const RadiusLayerPair &key) const
Calculate the avoidance areas at the radius and layer indicated by key.
Definition TreeSupport.cpp:4031
Convenience typedef for the keys to the caches.
Definition TreeSupport.hpp:270
void stage_add(TreeSupportStage stage)
Definition TreeSupport.cpp:200
void tic()
Definition TreeSupport.cpp:195
TreeSupportProfiler profiler
Definition TreeSupport.cpp:227
@ STAGE_GET_AVOIDANCE
Definition TreeSupport.cpp:155

References calculate_avoidance(), ceil_radius(), m_avoidance_cache, Slic3r::profiler, and Slic3r::STAGE_GET_AVOIDANCE.

Referenced by calculate_avoidance().

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

◆ get_collision()

const ExPolygons & Slic3r::TreeSupportData::get_collision ( coordf_t radius,
size_t layer_idx ) const

Creates the areas that have to be avoided by the tree's branches.

The result is a 2D area that would cause nodes of radius radius to collide with the model.

Parameters
radiusThe radius of the node of interest
layerThe layer of interest
Returns
Polygons object
3947{
3948 profiler.tic();
3949 radius = ceil_radius(radius);
3950 RadiusLayerPair key{radius, layer_nr};
3951 const auto it = m_collision_cache.find(key);
3952 const ExPolygons& collision = it != m_collision_cache.end() ? it->second : calculate_collision(key);
3954 return collision;
3955}
const ExPolygons & calculate_collision(const RadiusLayerPair &key) const
Calculate the collision areas at the radius and layer indicated by key.
Definition TreeSupport.cpp:4020
@ STAGE_get_collision
Definition TreeSupport.cpp:157

References calculate_collision(), ceil_radius(), m_collision_cache, Slic3r::profiler, and Slic3r::STAGE_get_collision.

Referenced by calculate_avoidance().

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

◆ get_contours()

Polygons Slic3r::TreeSupportData::get_contours ( size_t layer_nr) const
3970{
3971 Polygons contours;
3972 for (const ExPolygon& expoly : m_layer_outlines[layer_nr]) {
3973 contours.push_back(expoly.contour);
3974 }
3975
3976 return contours;
3977}
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22

References m_layer_outlines.

◆ get_contours_with_holes()

Polygons Slic3r::TreeSupportData::get_contours_with_holes ( size_t layer_nr) const
3980{
3981 Polygons contours;
3982 for (const ExPolygon& expoly : m_layer_outlines[layer_nr]) {
3983 for(int i=0;i<expoly.num_contours();i++)
3984 contours.push_back(expoly.contour_or_hole(i));
3985 }
3986 return contours;
3987}

References m_layer_outlines.

◆ operator=() [1/2]

TreeSupportData & Slic3r::TreeSupportData::operator= ( const TreeSupportData & )
delete

References TreeSupportData().

Here is the call graph for this function:

◆ operator=() [2/2]

TreeSupportData & Slic3r::TreeSupportData::operator= ( TreeSupportData && )
delete

References TreeSupportData().

Here is the call graph for this function:

Member Data Documentation

◆ branch_scale_factor

double Slic3r::TreeSupportData::branch_scale_factor = 1.0

Referenced by TreeSupportData().

◆ contact_nodes

std::vector<std::unique_ptr<SupportNode> > Slic3r::TreeSupportData::contact_nodes

Referenced by clear_nodes(), and create_node().

◆ is_slim

bool Slic3r::TreeSupportData::is_slim = false

◆ layer_heights

std::vector<LayerHeightData> Slic3r::TreeSupportData::layer_heights

◆ m_avoidance_cache

tbb::concurrent_unordered_map<RadiusLayerPair, ExPolygons, RadiusLayerPairHash, RadiusLayerPairEquality> Slic3r::TreeSupportData::m_avoidance_cache
mutable

◆ m_collision_cache

tbb::concurrent_unordered_map<RadiusLayerPair, ExPolygons, RadiusLayerPairHash, RadiusLayerPairEquality> Slic3r::TreeSupportData::m_collision_cache
mutable

Caches for the collision, avoidance and internal model polygons at given radius and layer indices.

These are mutable to allow modification from const function. This is generally considered OK as the functions are still logically const (ie there is no difference in behaviour for the user betweeen calculating the values each time vs caching the results).

coconut: previously stl::unordered_map is used which seems problematic with tbb::parallel_for. So we change to tbb::concurrent_unordered_map

Referenced by calculate_collision(), and get_collision().

◆ m_layer_outlines

std::vector<ExPolygons> Slic3r::TreeSupportData::m_layer_outlines

Storage for layer outlines of the meshes.

Referenced by TreeSupportData(), calculate_collision(), get_contours(), and get_contours_with_holes().

◆ m_layer_outlines_below

std::vector<ExPolygons> Slic3r::TreeSupportData::m_layer_outlines_below

Referenced by TreeSupportData().

◆ m_max_move_distances

std::vector<double> Slic3r::TreeSupportData::m_max_move_distances

◆ m_mutex

tbb::spin_mutex Slic3r::TreeSupportData::m_mutex
private

Referenced by clear_nodes(), and create_node().

◆ m_radius_sample_resolution

coordf_t Slic3r::TreeSupportData::m_radius_sample_resolution

Sample resolution for radius values.

The radius will be rounded (upwards) to multiples of this value before calculations are done when collision, avoidance and internal model Polygons are requested.

Referenced by TreeSupportData(), calculate_collision(), and ceil_radius().

◆ m_xy_distance

coordf_t Slic3r::TreeSupportData::m_xy_distance

The required clearance between the model and the tree branches.

Referenced by TreeSupportData(), and calculate_collision().

◆ TreeSupport

friend Slic3r::TreeSupportData::TreeSupport

The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Support/TreeSupport.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Support/TreeSupport.cpp