mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-10 16:27:54 -06:00
Clean up tree support code
(cherry picked from commit bambulab/BambuStudio@39ae64fc53) Co-authored-by: Arthur <arthur.tang@bambulab.com>
This commit is contained in:
parent
4034ffea18
commit
51290a853d
2 changed files with 223 additions and 477 deletions
|
@ -41,6 +41,142 @@ struct TreeNode {
|
|||
}
|
||||
};
|
||||
|
||||
enum TreeNodeType {
|
||||
eCircle,
|
||||
eSquare,
|
||||
ePolygon
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Represents the metadata of a node in the tree.
|
||||
*/
|
||||
struct SupportNode
|
||||
{
|
||||
static constexpr SupportNode* NO_PARENT = nullptr;
|
||||
|
||||
SupportNode()
|
||||
: distance_to_top(0)
|
||||
, position(Point(0, 0))
|
||||
, obj_layer_nr(0)
|
||||
, support_roof_layers_below(0)
|
||||
, support_floor_layers_above(0)
|
||||
, to_buildplate(true)
|
||||
, parent(nullptr)
|
||||
, print_z(0.0)
|
||||
, height(0.0)
|
||||
{}
|
||||
|
||||
// when dist_mm_to_top_==0, new node's dist_mm_to_top=parent->dist_mm_to_top + parent->height;
|
||||
SupportNode(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)
|
||||
: distance_to_top(distance_to_top)
|
||||
, position(position)
|
||||
, obj_layer_nr(obj_layer_nr)
|
||||
, support_roof_layers_below(support_roof_layers_below)
|
||||
, support_floor_layers_above(0)
|
||||
, to_buildplate(to_buildplate)
|
||||
, parent(parent)
|
||||
, print_z(print_z_)
|
||||
, height(height_)
|
||||
, dist_mm_to_top(dist_mm_to_top_)
|
||||
{
|
||||
if (parent) {
|
||||
type = parent->type;
|
||||
overhang = parent->overhang;
|
||||
if (dist_mm_to_top==0)
|
||||
dist_mm_to_top = parent->dist_mm_to_top + parent->height;
|
||||
parent->child = this;
|
||||
for (auto& neighbor : parent->merged_neighbours)
|
||||
neighbor->child = this;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG // Clear the delete node's data so if there's invalid access after, we may get a clue by inspecting that node.
|
||||
~SupportNode()
|
||||
{
|
||||
parent = nullptr;
|
||||
merged_neighbours.clear();
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
/*!
|
||||
* \brief The number of layers to go to the top of this branch.
|
||||
* Negative value means it's a virtual node between support and overhang, which doesn't need to be extruded.
|
||||
*/
|
||||
int distance_to_top;
|
||||
coordf_t dist_mm_to_top = 0; // dist to bottom contact in mm
|
||||
|
||||
/*!
|
||||
* \brief The position of this node on the layer.
|
||||
*/
|
||||
Point position;
|
||||
Point movement; // movement towards neighbor center or outline
|
||||
mutable double radius = 0.0;
|
||||
mutable double max_move_dist = 0.0;
|
||||
TreeNodeType type = eCircle;
|
||||
bool is_merged = false; // this node is generated by merging upper nodes
|
||||
bool is_corner = false;
|
||||
bool is_processed = false;
|
||||
const ExPolygon *overhang = nullptr; // when type==ePolygon, set this value to get original overhang area
|
||||
|
||||
/*!
|
||||
* \brief The direction of the skin lines above the tip of the branch.
|
||||
*
|
||||
* This determines in which direction we should reduce the width of the
|
||||
* branch.
|
||||
*/
|
||||
bool skin_direction;
|
||||
|
||||
/*!
|
||||
* \brief The number of support roof layers below this one.
|
||||
*
|
||||
* When a contact point is created, it is determined whether the mesh
|
||||
* needs to be supported with support roof or not, since that is a
|
||||
* per-mesh setting. This is stored in this variable in order to track
|
||||
* how far we need to extend that support roof downwards.
|
||||
*/
|
||||
int support_roof_layers_below;
|
||||
int support_floor_layers_above;
|
||||
int obj_layer_nr;
|
||||
|
||||
/*!
|
||||
* \brief Whether to try to go towards the build plate.
|
||||
*
|
||||
* If the node is inside the collision areas, it has no choice but to go
|
||||
* towards the model. If it is not inside the collision areas, it must
|
||||
* go towards the build plate to prevent a scar on the surface.
|
||||
*/
|
||||
bool to_buildplate;
|
||||
|
||||
/*!
|
||||
* \brief The originating node for this one, one layer higher.
|
||||
*
|
||||
* In order to prune branches that can't have any support (because they
|
||||
* can't be on the model and the path to the buildplate isn't clear),
|
||||
* the entire branch needs to be known.
|
||||
*/
|
||||
SupportNode* parent;
|
||||
SupportNode* child = nullptr;
|
||||
|
||||
/*!
|
||||
* \brief All neighbours (on the same layer) that where merged into this node.
|
||||
*
|
||||
* In order to prune branches that can't have any support (because they
|
||||
* can't be on the model and the path to the buildplate isn't clear),
|
||||
* the entire branch needs to be known.
|
||||
*/
|
||||
std::list<SupportNode*> merged_neighbours;
|
||||
|
||||
coordf_t print_z;
|
||||
coordf_t height;
|
||||
|
||||
bool operator==(const SupportNode& other) const
|
||||
{
|
||||
return position == other.position;
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Lazily generates tree guidance volumes.
|
||||
*
|
||||
|
@ -227,140 +363,6 @@ public:
|
|||
|
||||
void detect_overhangs(bool detect_first_sharp_tail_only=false);
|
||||
|
||||
enum NodeType {
|
||||
eCircle,
|
||||
eSquare,
|
||||
ePolygon
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Represents the metadata of a node in the tree.
|
||||
*/
|
||||
struct Node
|
||||
{
|
||||
static constexpr Node* NO_PARENT = nullptr;
|
||||
|
||||
Node()
|
||||
: distance_to_top(0)
|
||||
, position(Point(0, 0))
|
||||
, obj_layer_nr(0)
|
||||
, support_roof_layers_below(0)
|
||||
, support_floor_layers_above(0)
|
||||
, to_buildplate(true)
|
||||
, parent(nullptr)
|
||||
, print_z(0.0)
|
||||
, height(0.0)
|
||||
{}
|
||||
|
||||
// when dist_mm_to_top_==0, new node's dist_mm_to_top=parent->dist_mm_to_top + parent->height;
|
||||
Node(const Point position, const int distance_to_top, const int obj_layer_nr, const int support_roof_layers_below, const bool to_buildplate, Node* parent,
|
||||
coordf_t print_z_, coordf_t height_, coordf_t dist_mm_to_top_=0)
|
||||
: distance_to_top(distance_to_top)
|
||||
, position(position)
|
||||
, obj_layer_nr(obj_layer_nr)
|
||||
, support_roof_layers_below(support_roof_layers_below)
|
||||
, support_floor_layers_above(0)
|
||||
, to_buildplate(to_buildplate)
|
||||
, parent(parent)
|
||||
, print_z(print_z_)
|
||||
, height(height_)
|
||||
, dist_mm_to_top(dist_mm_to_top_)
|
||||
{
|
||||
if (parent) {
|
||||
type = parent->type;
|
||||
overhang = parent->overhang;
|
||||
if (dist_mm_to_top==0)
|
||||
dist_mm_to_top = parent->dist_mm_to_top + parent->height;
|
||||
parent->child = this;
|
||||
for (auto& neighbor : parent->merged_neighbours)
|
||||
neighbor->child = this;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG // Clear the delete node's data so if there's invalid access after, we may get a clue by inspecting that node.
|
||||
~Node()
|
||||
{
|
||||
parent = nullptr;
|
||||
merged_neighbours.clear();
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
/*!
|
||||
* \brief The number of layers to go to the top of this branch.
|
||||
* Negative value means it's a virtual node between support and overhang, which doesn't need to be extruded.
|
||||
*/
|
||||
int distance_to_top;
|
||||
coordf_t dist_mm_to_top = 0; // dist to bottom contact in mm
|
||||
|
||||
/*!
|
||||
* \brief The position of this node on the layer.
|
||||
*/
|
||||
Point position;
|
||||
Point movement; // movement towards neighbor center or outline
|
||||
mutable double radius = 0.0;
|
||||
mutable double max_move_dist = 0.0;
|
||||
NodeType type = eCircle;
|
||||
bool is_merged = false; // this node is generated by merging upper nodes
|
||||
bool is_corner = false;
|
||||
bool is_processed = false;
|
||||
const ExPolygon *overhang = nullptr; // when type==ePolygon, set this value to get original overhang area
|
||||
|
||||
/*!
|
||||
* \brief The direction of the skin lines above the tip of the branch.
|
||||
*
|
||||
* This determines in which direction we should reduce the width of the
|
||||
* branch.
|
||||
*/
|
||||
bool skin_direction;
|
||||
|
||||
/*!
|
||||
* \brief The number of support roof layers below this one.
|
||||
*
|
||||
* When a contact point is created, it is determined whether the mesh
|
||||
* needs to be supported with support roof or not, since that is a
|
||||
* per-mesh setting. This is stored in this variable in order to track
|
||||
* how far we need to extend that support roof downwards.
|
||||
*/
|
||||
int support_roof_layers_below;
|
||||
int support_floor_layers_above;
|
||||
int obj_layer_nr;
|
||||
|
||||
/*!
|
||||
* \brief Whether to try to go towards the build plate.
|
||||
*
|
||||
* If the node is inside the collision areas, it has no choice but to go
|
||||
* towards the model. If it is not inside the collision areas, it must
|
||||
* go towards the build plate to prevent a scar on the surface.
|
||||
*/
|
||||
bool to_buildplate;
|
||||
|
||||
/*!
|
||||
* \brief The originating node for this one, one layer higher.
|
||||
*
|
||||
* In order to prune branches that can't have any support (because they
|
||||
* can't be on the model and the path to the buildplate isn't clear),
|
||||
* the entire branch needs to be known.
|
||||
*/
|
||||
Node *parent;
|
||||
Node *child = nullptr;
|
||||
|
||||
/*!
|
||||
* \brief All neighbours (on the same layer) that where merged into this node.
|
||||
*
|
||||
* In order to prune branches that can't have any support (because they
|
||||
* can't be on the model and the path to the buildplate isn't clear),
|
||||
* the entire branch needs to be known.
|
||||
*/
|
||||
std::list<Node*> merged_neighbours;
|
||||
|
||||
coordf_t print_z;
|
||||
coordf_t height;
|
||||
|
||||
bool operator==(const Node& other) const
|
||||
{
|
||||
return position == other.position;
|
||||
}
|
||||
};
|
||||
|
||||
int avg_node_per_layer = 0;
|
||||
float nodes_angle = 0;
|
||||
|
@ -418,7 +420,7 @@ private:
|
|||
* save the resulting support polygons to.
|
||||
* \param contact_nodes The nodes to draw as support.
|
||||
*/
|
||||
void draw_circles(const std::vector<std::vector<Node*>>& contact_nodes);
|
||||
void draw_circles(const std::vector<std::vector<SupportNode*>>& contact_nodes);
|
||||
|
||||
/*!
|
||||
* \brief Drops down the nodes of the tree support towards the build plate.
|
||||
|
@ -432,18 +434,18 @@ private:
|
|||
* dropped down. The nodes are dropped to lower layers inside the same
|
||||
* vector of layers.
|
||||
*/
|
||||
void drop_nodes(std::vector<std::vector<Node *>> &contact_nodes);
|
||||
void drop_nodes(std::vector<std::vector<SupportNode*>>& contact_nodes);
|
||||
|
||||
void smooth_nodes(std::vector<std::vector<Node *>> &contact_nodes);
|
||||
void smooth_nodes(std::vector<std::vector<SupportNode*>>& contact_nodes);
|
||||
|
||||
void adjust_layer_heights(std::vector<std::vector<Node*>>& contact_nodes);
|
||||
void adjust_layer_heights(std::vector<std::vector<SupportNode*>>& contact_nodes);
|
||||
|
||||
/*! BBS: MusangKing: maximum layer height
|
||||
* \brief Optimize the generation of tree support by pre-planning the layer_heights
|
||||
*
|
||||
*/
|
||||
|
||||
std::vector<LayerHeightData> plan_layer_heights(std::vector<std::vector<Node *>> &contact_nodes);
|
||||
std::vector<LayerHeightData> plan_layer_heights(std::vector<std::vector<SupportNode*>>& contact_nodes);
|
||||
/*!
|
||||
* \brief Creates points where support contacts the model.
|
||||
*
|
||||
|
@ -457,18 +459,16 @@ private:
|
|||
* \return For each layer, a list of points where the tree should connect
|
||||
* with the model.
|
||||
*/
|
||||
void generate_contact_points(std::vector<std::vector<Node*>>& contact_nodes);
|
||||
void generate_contact_points(std::vector<std::vector<SupportNode*>>& contact_nodes);
|
||||
|
||||
/*!
|
||||
* \brief Add a node to the next layer.
|
||||
*
|
||||
* If a node is already at that position in the layer, the nodes are merged.
|
||||
*/
|
||||
void insert_dropped_node(std::vector<Node*>& nodes_layer, Node* node);
|
||||
void insert_dropped_node(std::vector<SupportNode*>& nodes_layer, SupportNode* node);
|
||||
void create_tree_support_layers();
|
||||
void generate_toolpaths();
|
||||
Polygons spanning_tree_to_polygon(const std::vector<MinimumSpanningTree>& spanning_trees, Polygons layer_contours, int layer_nr);
|
||||
Polygons contact_nodes_to_polygon(const std::vector<Node*>& contact_nodes, Polygons layer_contours, int layer_nr, std::vector<double>& radiis, std::vector<bool>& is_interface);
|
||||
coordf_t calc_branch_radius(coordf_t base_radius, size_t layers_to_top, size_t tip_layers, double diameter_angle_scale_factor);
|
||||
coordf_t calc_branch_radius(coordf_t base_radius, coordf_t mm_to_top, double diameter_angle_scale_factor);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue