OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::FillLightning::Node Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Fill/Lightning/TreeNode.hpp>

Inheritance diagram for Slic3r::FillLightning::Node:
Collaboration diagram for Slic3r::FillLightning::Node:

Classes

struct  RectilinearJunction

Public Member Functions

const Point & getLocation () const
void setLocation (const Point &p)
NodeSPtr addChild (const Point &p)
NodeSPtr addChild (NodeSPtr &new_child)
void propagateToNextLayer (std::vector< NodeSPtr > &next_trees, const Polygons &next_outlines, const EdgeGrid::Grid &outline_locator, coord_t prune_distance, coord_t smooth_magnitude, coord_t max_remove_colinear_dist) const
void visitBranches (const std::function< void(const Point &, const Point &)> &visitor) const
void visitNodes (const std::function< void(NodeSPtr)> &visitor)
coord_t getWeightedDistance (const Point &unsupported_location, const coord_t &supporting_radius) const
bool isRoot () const
void reroot (const NodeSPtr &new_parent=nullptr)
NodeSPtr closestNode (const Point &loc)
bool hasOffspring (const NodeSPtr &to_be_checked) const
 Node ()=delete
void convertToPolylines (Polylines &output, coord_t line_overlap) const
const std::optional< Point > & getLastGroundingLocation () const
void draw_tree (SVG &svg)

Static Public Member Functions

template<typename ... Arg>
static NodeSPtr create (Arg &&...arg)

Protected Member Functions

 Node (const Point &p, const std::optional< Point > &last_grounding_location=std::nullopt)
NodeSPtr deepCopy () const
bool realign (const Polygons &outlines, const EdgeGrid::Grid &outline_locator, std::vector< NodeSPtr > &rerooted_parts)
void straighten (coord_t magnitude, coord_t max_remove_colinear_dist)
RectilinearJunction straighten (coord_t magnitude, const Point &junction_above, coord_t accumulated_dist, int64_t max_remove_colinear_dist2)
coord_t prune (const coord_t &distance)
void convertToPolylines (size_t long_line_idx, Polylines &output, std::mt19937_64 &rng) const
void removeJunctionOverlap (Polylines &polylines, coord_t line_overlap) const

Protected Attributes

bool m_is_root
Point m_p
std::weak_ptr< Node > m_parent
std::vector< NodeSPtr > m_children
std::optional< Point > m_last_grounding_location

Friends

BoundingBox get_extents (const NodeSPtr &root_node)
BoundingBox get_extents (const std::vector< NodeSPtr > &tree_roots)

Detailed Description

A single vertex of a Lightning Tree, the structure that determines the paths to be printed to form Lightning Infill.

In essence these vertices are just a position linked to other positions in 2D. The nodes have a hierarchical structure of parents and children, forming a tree. The class also has some helper functions specific to Lightning Infill e.g. to straighten the paths around this node.


Class Documentation

◆ Slic3r::FillLightning::Node::RectilinearJunction

struct Slic3r::FillLightning::Node::RectilinearJunction
Collaboration diagram for Slic3r::FillLightning::Node::RectilinearJunction:
Class Members
Point junction_loc junction location below
coord_t total_recti_dist rectilinear distance along the tree from the last junction above to the junction below

Constructor & Destructor Documentation

◆ Node() [1/2]

Slic3r::FillLightning::Node::Node ( )
delete

Referenced by convertToPolylines(), and create().

Here is the caller graph for this function:

◆ Node() [2/2]

Slic3r::FillLightning::Node::Node ( const Point & p,
const std::optional< Point > & last_grounding_location = std::nullopt )
explicitprotected

Construct a new node, either for insertion in a tree or as root.

Parameters
pThe physical location in the 2D layer that this node represents. Connecting other nodes to this node indicates that a line segment should be drawn between those two physical positions.
103 :
104 m_is_root(true), m_p(p), m_last_grounding_location(last_grounding_location)
105{}
std::optional< Point > m_last_grounding_location
Definition TreeNode.hpp:281
Point m_p
Definition TreeNode.hpp:277
bool m_is_root
Definition TreeNode.hpp:276

References m_is_root, m_last_grounding_location, and m_p.

Member Function Documentation

◆ addChild() [1/2]

NodeSPtr Slic3r::FillLightning::Node::addChild ( const Point & p)

Construct a new Node instance and add it as a child of this node.

Parameters
pThe location of the new node.
Returns
A shared pointer to the new node.
51{
52 assert(m_p != child_loc);
53 NodeSPtr child = Node::create(child_loc);
54 return addChild(child);
55}
static NodeSPtr create(Arg &&...arg)
Definition TreeNode.hpp:53
NodeSPtr addChild(const Point &p)
Definition TreeNode.cpp:50
std::shared_ptr< Node > NodeSPtr
Definition Layer.hpp:25

References addChild(), create(), and m_p.

Referenced by addChild().

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

◆ addChild() [2/2]

NodeSPtr Slic3r::FillLightning::Node::addChild ( NodeSPtr & new_child)

Add an existing Node as a child of this node.

Parameters
new_childThe node that must be added as a child.
Returns
Always returns new_child.
58{
59 assert(new_child != shared_from_this());
60 //assert(p != new_child->p); // NOTE: No problem for now. Issue to solve later. Maybe even afetr final. Low prio.
61 m_children.push_back(new_child);
62 new_child->m_parent = shared_from_this();
63 new_child->m_is_root = false;
64 return new_child;
65}
std::vector< NodeSPtr > m_children
Definition TreeNode.hpp:279

References m_children.

◆ closestNode()

NodeSPtr Slic3r::FillLightning::Node::closestNode ( const Point & loc)

Retrieves the closest node to the specified location.

Parameters
locThe specified location.
Returns
The branch that starts at the position closest to the location within this tree.
144{
145 NodeSPtr result = shared_from_this();
146 auto closest_dist2 = coord_t((m_p - loc).cast<double>().norm());
147
148 for (const auto& child : m_children) {
149 NodeSPtr candidate_node = child->closestNode(loc);
150 const auto child_dist2 = coord_t((candidate_node->m_p - loc).cast<double>().norm());
151 if (child_dist2 < closest_dist2) {
152 closest_dist2 = child_dist2;
153 result = candidate_node;
154 }
155 }
156
157 return result;
158}
int64_t coord_t
Definition libslic3r.h:48
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299

References Slic3r::cast(), m_children, and m_p.

Here is the call graph for this function:

◆ convertToPolylines() [1/2]

void Slic3r::FillLightning::Node::convertToPolylines ( Polylines & output,
coord_t line_overlap ) const

Convert the tree into polylines

At each junction one line is chosen at random to continue

The lines start at a leaf and end in a junction

Parameters
outputall branches in this tree connected into polylines
360{
361 Polylines result;
362 result.emplace_back();
363 // Orca: the layers are filled in parallel, so they would consume a shared generator in a
364 // different order every run, and a model would not slice the same way twice. Each tree seeds
365 // its own from where it is rooted; one constant seed would start them all on the same pick.
366 std::mt19937_64 rng { uint64_t(PointHash{}(m_p)) };
367 convertToPolylines(0, result, rng);
368 removeJunctionOverlap(result, line_overlap);
369 append(output, std::move(result));
370}
void convertToPolylines(Polylines &output, coord_t line_overlap) const
Definition TreeNode.cpp:359
void removeJunctionOverlap(Polylines &polylines, coord_t line_overlap) const
Definition TreeNode.cpp:392
std::vector< Polyline > Polylines
Definition Polyline.hpp:22
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:157

References Slic3r::append(), convertToPolylines(), m_p, and removeJunctionOverlap().

Referenced by convertToPolylines(), and convertToPolylines().

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

◆ convertToPolylines() [2/2]

void Slic3r::FillLightning::Node::convertToPolylines ( size_t long_line_idx,
Polylines & output,
std::mt19937_64 & rng ) const
protected

Convert the tree into polylines

At each junction one line is chosen at random to continue

The lines start at a leaf and end in a junction

Parameters
long_linea reference to a polyline in output which to continue building on in the recursion
outputall branches in this tree connected into polylines
rngthe generator the junctions draw from, carried through the recursion
373{
374 if (m_children.empty()) {
375 output[long_line_idx].points.push_back(m_p);
376 return;
377 }
378 const size_t first_child_idx = rng() % m_children.size();
379 m_children[first_child_idx]->convertToPolylines(long_line_idx, output, rng);
380 output[long_line_idx].points.push_back(m_p);
381
382 for (size_t idx_offset = 1; idx_offset < m_children.size(); idx_offset++) {
383 size_t child_idx = (first_child_idx + idx_offset) % m_children.size();
384 const Node& child = *m_children[child_idx];
385 output.emplace_back();
386 size_t child_line_idx = output.size() - 1;
387 child.convertToPolylines(child_line_idx, output, rng);
388 output[child_line_idx].points.emplace_back(m_p);
389 }
390}

References Node(), convertToPolylines(), m_children, and m_p.

Here is the call graph for this function:

◆ create()

template<typename ... Arg>
NodeSPtr Slic3r::FillLightning::Node::create ( Arg &&... arg)
inlinestatic
54 {
55 struct EnableMakeShared : public Node
56 {
57 explicit EnableMakeShared(Arg&&...arg) : Node(std::forward<Arg>(arg)...) {}
58 };
59 return std::make_shared<EnableMakeShared>(std::forward<Arg>(arg)...);
60 }

References Node().

Referenced by addChild(), Slic3r::FillLightning::Layer::attach(), deepCopy(), and Slic3r::FillLightning::Layer::reconnectRoots().

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

◆ deepCopy()

NodeSPtr Slic3r::FillLightning::Node::deepCopy ( ) const
protected

Copy this node and its entire sub-tree.

Returns
The equivalent of this node in the copy (the root of the new sub- tree).
108{
109 NodeSPtr local_root = Node::create(m_p);
110 local_root->m_is_root = m_is_root;
111 if (m_is_root)
112 {
113 local_root->m_last_grounding_location = m_last_grounding_location.value_or(m_p);
114 }
115 local_root->m_children.reserve(m_children.size());
116 for (const auto& node : m_children)
117 {
118 NodeSPtr child = node->deepCopy();
119 child->m_parent = local_root;
120 local_root->m_children.push_back(child);
121 }
122 return local_root;
123}

References create(), m_children, m_is_root, m_last_grounding_location, and m_p.

Referenced by propagateToNextLayer().

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

◆ draw_tree()

void Slic3r::FillLightning::Node::draw_tree ( SVG & svg)
inline
258{ for (auto& child : m_children) { svg.draw(Line(m_p, child->getLocation()), "yellow"); child->draw_tree(svg); } }

References Slic3r::SVG::draw(), m_children, and m_p.

Here is the call graph for this function:

◆ getLastGroundingLocation()

const std::optional< Point > & Slic3r::FillLightning::Node::getLastGroundingLocation ( ) const
inline

If this was ever a direct child of the root, it'll have a previous grounding location.

This needs to be known when roots are reconnected, so that the last (higher) layer is supported by the next one.

References m_last_grounding_location.

◆ getLocation()

const Point & Slic3r::FillLightning::Node::getLocation ( ) const
inline

Get the position on this layer that this node represents, a vertex of the path to print.

Returns
The position that this node represents.
67{ return m_p; }

References m_p.

Referenced by get_extents, getWeightedDistance(), and prune().

Here is the caller graph for this function:

◆ getWeightedDistance()

coord_t Slic3r::FillLightning::Node::getWeightedDistance ( const Point & unsupported_location,
const coord_t & supporting_radius ) const

Get a weighted distance from an unsupported point to this node (given the current supporting radius).

When attaching a unsupported location to a node, not all nodes have the same priority. (Eucludian) closer nodes are prioritised, but that's not the whole story. For instance, we give some nodes a 'valence boost' depending on the nr. of branches.

Parameters
unsupported_locationThe (unsuppported) location of which the weighted distance needs to be calculated.
supporting_radiusThe maximum distance which can be bridged without (infill) supporting it.
Returns
The weighted distance.
27{
28 constexpr coord_t min_valence_for_boost = 0;
29 constexpr coord_t max_valence_for_boost = 4;
30 constexpr coord_t valence_boost_multiplier = 4;
31
32 const size_t valence = (!m_is_root) + m_children.size();
33 const coord_t valence_boost = (min_valence_for_boost < valence && valence < max_valence_for_boost) ? valence_boost_multiplier * supporting_radius : 0;
34 const auto dist_here = coord_t((getLocation() - unsupported_location).cast<double>().norm());
35 return dist_here - valence_boost;
36}
const Point & getLocation() const
Definition TreeNode.hpp:67

References Slic3r::cast(), getLocation(), m_children, and m_is_root.

Here is the call graph for this function:

◆ hasOffspring()

bool Slic3r::FillLightning::Node::hasOffspring ( const NodeSPtr & to_be_checked) const

Returns whether the given tree node is a descendant of this node.

If this node itself is given, it is also considered to be a descendant.

Parameters
to_be_checkedA node to find out whether it is a descendant of this node.
Returns
true if the given node is a descendant or this node itself, or false if it is not in the sub-tree.
39{
40 if (to_be_checked == shared_from_this())
41 return true;
42
43 for (auto& child_ptr : m_children)
44 if (child_ptr->hasOffspring(to_be_checked))
45 return true;
46
47 return false;
48}

References m_children.

◆ isRoot()

bool Slic3r::FillLightning::Node::isRoot ( ) const
inline

Returns whether this node is the root of a lightning tree. It is the root if it has no parents.

Returns
true if this node is the root (no parents) or false if it is a child node of some other node.
161{ return m_is_root; }

References m_is_root.

◆ propagateToNextLayer()

void Slic3r::FillLightning::Node::propagateToNextLayer ( std::vector< NodeSPtr > & next_trees,
const Polygons & next_outlines,
const EdgeGrid::Grid & outline_locator,
coord_t prune_distance,
coord_t smooth_magnitude,
coord_t max_remove_colinear_dist ) const

Propagate this node's sub-tree to the next layer.

Creates a copy of this tree, realign it to the new layer boundaries next_outlines and reduce (i.e. prune and straighten) it. A copy of this node and all of its descendant nodes will be added to the next_trees vector.

Parameters
next_treesA collection of tree nodes to use for the next layer.
next_outlinesThe shape of the layer below, to make sure that the tree stays within the bounds of the infill area.
prune_distanceThe maximum distance that a leaf node may be moved such that it still supports the current node.
smooth_magnitudeThe maximum distance that a line may be shifted to straighten the tree's paths, such that it still supports the current paths.
max_remove_colinear_distThe maximum distance of a line-segment from which straightening may remove a colinear point.
74{
75 auto tree_below = deepCopy();
76 tree_below->prune(prune_distance);
77 tree_below->straighten(smooth_magnitude, max_remove_colinear_dist);
78 if (tree_below->realign(next_outlines, outline_locator, next_trees))
79 next_trees.push_back(tree_below);
80}
NodeSPtr deepCopy() const
Definition TreeNode.cpp:107

References deepCopy().

Here is the call graph for this function:

◆ prune()

coord_t Slic3r::FillLightning::Node::prune ( const coord_t & distance)
protected

Prune the tree from the extremeties (leaf-nodes) until the pruning distance is reached.

Returns
The distance that has been pruned. If less than distance, then the whole tree was puned away.
323{
324 if (pruning_distance <= 0)
325 return 0;
326
327 coord_t max_distance_pruned = 0;
328 for (auto child_it = m_children.begin(); child_it != m_children.end(); ) {
329 auto& child = *child_it;
330 coord_t dist_pruned_child = child->prune(pruning_distance);
331 if (dist_pruned_child >= pruning_distance)
332 { // pruning is finished for child; dont modify further
333 max_distance_pruned = std::max(max_distance_pruned, dist_pruned_child);
334 ++child_it;
335 } else {
336 const Point a = getLocation();
337 const Point b = child->getLocation();
338 const Point ba = a - b;
339 const auto ab_len = coord_t(ba.cast<double>().norm());
340 if (dist_pruned_child + ab_len <= pruning_distance) {
341 // we're still in the process of pruning
342 assert(child->m_children.empty() && "when pruning away a node all it's children must already have been pruned away");
343 max_distance_pruned = std::max(max_distance_pruned, dist_pruned_child + ab_len);
344 child_it = m_children.erase(child_it);
345 } else {
346 // pruning stops in between this node and the child
347 const Point n = b + (ba.cast<double>().normalized() * (pruning_distance - dist_pruned_child)).cast<coord_t>();
348 assert(std::abs((n - b).cast<double>().norm() + dist_pruned_child - pruning_distance) < 10 && "total pruned distance must be equal to the pruning_distance");
349 max_distance_pruned = std::max(max_distance_pruned, pruning_distance);
350 child->setLocation(n);
351 ++child_it;
352 }
353 }
354 }
355
356 return max_distance_pruned;
357}
Kernel::Point_3 Point
Definition MeshRepair.cpp:81

References Slic3r::cast(), getLocation(), m_children, and prune().

Referenced by prune().

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

◆ realign()

bool Slic3r::FillLightning::Node::realign ( const Polygons & outlines,
const EdgeGrid::Grid & outline_locator,
std::vector< NodeSPtr > & rerooted_parts )
protected

Reconnect trees from the layer above to the new outlines of the lower layer.

Returns
Wether or not the root is kept (false is no, true is yes).
200{
201 if (outlines.empty())
202 return false;
203
204 if (inside(outlines, m_p)) {
205 // Only keep children that have an unbroken connection to here, realign will put the rest in rerooted parts due to recursion:
206 Point coll;
207 bool reground_me = false;
208 m_children.erase(std::remove_if(m_children.begin(), m_children.end(), [&](const NodeSPtr &child) {
209 bool connect_branch = child->realign(outlines, outline_locator, rerooted_parts);
210 // Find an intersection of the line segment from p to child->p, at maximum outline_locator.resolution() * 2 distance from p.
211 if (connect_branch && lineSegmentPolygonsIntersection(child->m_p, m_p, outline_locator, coll, outline_locator.resolution() * 2)) {
212 child->m_last_grounding_location.reset();
213 child->m_parent.reset();
214 child->m_is_root = true;
215 rerooted_parts.push_back(child);
216 reground_me = true;
217 connect_branch = false;
218 }
219 return ! connect_branch;
220 }), m_children.end());
221 if (reground_me)
223 return true;
224 }
225
226 // 'Lift' any decendants out of this tree:
227 for (auto& child : m_children)
228 if (child->realign(outlines, outline_locator, rerooted_parts)) {
229 child->m_last_grounding_location = m_p;
230 child->m_parent.reset();
231 child->m_is_root = true;
232 rerooted_parts.push_back(child);
233 }
234
235 m_children.clear();
236 return false;
237}
bool inside(const Polygons &polygons, const Point &p)
Definition TreeNode.cpp:160

References Slic3r::FillLightning::inside(), m_children, m_last_grounding_location, and m_p.

Here is the call graph for this function:

◆ removeJunctionOverlap()

void Slic3r::FillLightning::Node::removeJunctionOverlap ( Polylines & polylines,
coord_t line_overlap ) const
protected
393{
394 const coord_t reduction = line_overlap;
395 size_t res_line_idx = 0;
396 while (res_line_idx < result_lines.size()) {
397 Polyline &polyline = result_lines[res_line_idx];
398 if (polyline.size() <= 1) {
399 polyline = std::move(result_lines.back());
400 result_lines.pop_back();
401 continue;
402 }
403
404 coord_t to_be_reduced = reduction;
405 Point a = polyline.back();
406 for (int point_idx = int(polyline.size()) - 2; point_idx >= 0; point_idx--) {
407 const Point b = polyline.points[point_idx];
408 const Point ab = b - a;
409 const auto ab_len = coord_t(ab.cast<double>().norm());
410 if (ab_len >= to_be_reduced) {
411 polyline.points.back() = a + (ab.cast<double>() * (double(to_be_reduced) / ab_len)).cast<coord_t>();
412 break;
413 } else {
414 to_be_reduced -= ab_len;
415 polyline.points.pop_back();
416 }
417 a = b;
418 }
419
420 if (polyline.size() <= 1) {
421 polyline = std::move(result_lines.back());
422 result_lines.pop_back();
423 } else
424 ++ res_line_idx;
425 }
426}

References Slic3r::MultiPoint::back(), Slic3r::cast(), Slic3r::MultiPoint::points, removeJunctionOverlap(), and Slic3r::MultiPoint::size().

Referenced by convertToPolylines(), and removeJunctionOverlap().

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

◆ reroot()

void Slic3r::FillLightning::Node::reroot ( const NodeSPtr & new_parent = nullptr)

Reverse the parent-child relationship all the way to the root, from this node onward. This has the effect of 're-rooting' the tree at the current node if no immediate parent is given as argument. That is, the current node will become the root, it's (former) parent if any, will become one of it's children. This is then recursively bubbled up until it reaches the (former) root, which then will become a leaf.

Parameters
new_parentThe (new) parent-node of the root, useful for recursing or immediately attaching the node to another tree.
126{
127 if (! m_is_root) {
128 auto old_parent = m_parent.lock();
129 old_parent->reroot(shared_from_this());
130 m_children.push_back(old_parent);
131 }
132
133 if (new_parent) {
134 m_children.erase(std::remove(m_children.begin(), m_children.end(), new_parent), m_children.end());
135 m_is_root = false;
136 m_parent = new_parent;
137 } else {
138 m_is_root = true;
139 m_parent.reset();
140 }
141}
std::weak_ptr< Node > m_parent
Definition TreeNode.hpp:278

References m_children, m_is_root, and m_parent.

◆ setLocation()

void Slic3r::FillLightning::Node::setLocation ( const Point & p)
inline

Change the position on this layer that the node represents.

Parameters
pThe position that the node needs to represent.
73{ m_p = p; }

References m_p.

◆ straighten() [1/2]

Node::RectilinearJunction Slic3r::FillLightning::Node::straighten ( coord_t magnitude,
const Point & junction_above,
coord_t accumulated_dist,
int64_t max_remove_colinear_dist2 )
protected

Recursive part of straighten(.)

Parameters
junction_aboveThe last seen junction with multiple children above
accumulated_distThe distance along the tree from the last seen junction to this node
max_remove_colinear_dist2Maximum distance squared of the (compound) line-segment from which a co-linear point may be removed.
Returns
the total distance along the tree from the last junction above to the first next junction below and the location of the next junction below
249{
250 constexpr coord_t junction_magnitude_factor_numerator = 3;
251 constexpr coord_t junction_magnitude_factor_denominator = 4;
252
253 const coord_t junction_magnitude = magnitude * junction_magnitude_factor_numerator / junction_magnitude_factor_denominator;
254 if (m_children.size() == 1)
255 {
256 auto child_p = m_children.front();
257 auto child_dist = coord_t((m_p - child_p->m_p).cast<double>().norm());
258 RectilinearJunction junction_below = child_p->straighten(magnitude, junction_above, accumulated_dist + child_dist, max_remove_colinear_dist2);
259 coord_t total_dist_to_junction_below = junction_below.total_recti_dist;
260 const Point& a = junction_above;
261 Point b = junction_below.junction_loc;
262 if (a != b) // should always be true!
263 {
264 Point ab = b - a;
265 Point destination = (a.cast<int64_t>() + ab.cast<int64_t>() * int64_t(accumulated_dist) / std::max(int64_t(1), int64_t(total_dist_to_junction_below))).cast<coord_t>();
266 if ((destination - m_p).cast<int64_t>().squaredNorm() <= int64_t(magnitude) * int64_t(magnitude))
267 m_p = destination;
268 else
269 m_p += ((destination - m_p).cast<double>().normalized() * magnitude).cast<coord_t>();
270 }
271 { // remove nodes on linear segments
272 constexpr coord_t close_enough = 10;
273
274 child_p = m_children.front(); //recursive call to straighten might have removed the child
275 const NodeSPtr& parent_node = m_parent.lock();
276 if (parent_node &&
277 (child_p->m_p - parent_node->m_p).cast<int64_t>().squaredNorm() < max_remove_colinear_dist2 &&
278 Line::distance_to_squared(m_p, parent_node->m_p, child_p->m_p) < close_enough * close_enough) {
279 child_p->m_parent = m_parent;
280 for (auto& sibling : parent_node->m_children)
281 { // find this node among siblings
282 if (sibling == shared_from_this())
283 {
284 sibling = child_p; // replace this node by child
285 break;
286 }
287 }
288 }
289 }
290 return junction_below;
291 }
292 else
293 {
294 constexpr coord_t weight = 1000;
295 Point junction_moving_dir = ((junction_above - m_p).cast<double>().normalized() * weight).cast<coord_t>();
296 bool prevent_junction_moving = false;
297 for (auto& child_p : m_children)
298 {
299 const auto child_dist = coord_t((m_p - child_p->m_p).cast<double>().norm());
300 RectilinearJunction below = child_p->straighten(magnitude, m_p, child_dist, max_remove_colinear_dist2);
301
302 junction_moving_dir += ((below.junction_loc - m_p).cast<double>().normalized() * weight).cast<coord_t>();
303 if (below.total_recti_dist < magnitude) // TODO: make configurable?
304 {
305 prevent_junction_moving = true; // prevent flipflopping in branches due to straightening and junctoin moving clashing
306 }
307 }
308 if (junction_moving_dir != Point(0, 0) && ! m_children.empty() && ! m_is_root && ! prevent_junction_moving)
309 {
310 auto junction_moving_dir_len = coord_t(junction_moving_dir.norm());
311 if (junction_moving_dir_len > junction_magnitude)
312 {
313 junction_moving_dir = junction_moving_dir * junction_magnitude / junction_moving_dir_len;
314 }
315 m_p += junction_moving_dir;
316 }
317 return RectilinearJunction{ accumulated_dist, m_p };
318 }
319}
coord_t total_recti_dist
rectilinear distance along the tree from the last junction above to the junction below
Definition TreeNode.hpp:215
double distance_to_squared(const Point &point) const
Definition Line.hpp:170

References Slic3r::cast(), Slic3r::Line::distance_to_squared(), Slic3r::FillLightning::Node::RectilinearJunction::junction_loc, m_children, m_is_root, m_p, m_parent, straighten(), and Slic3r::FillLightning::Node::RectilinearJunction::total_recti_dist.

Here is the call graph for this function:

◆ straighten() [2/2]

void Slic3r::FillLightning::Node::straighten ( coord_t magnitude,
coord_t max_remove_colinear_dist )
protected

Smoothen the tree to make it a bit more printable, while still supporting the trees above.

Parameters
magnitudeThe maximum allowed distance to move the node.
max_remove_colinear_distMaximum distance of the (compound) line-segment from which a co-linear point may be removed.
240{
241 straighten(magnitude, m_p, 0, int64_t(max_remove_colinear_dist) * int64_t(max_remove_colinear_dist));
242}
void straighten(coord_t magnitude, coord_t max_remove_colinear_dist)
Definition TreeNode.cpp:239

References m_p, and straighten().

Referenced by straighten(), and straighten().

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

◆ visitBranches()

void Slic3r::FillLightning::Node::visitBranches ( const std::function< void(const Point &, const Point &)> & visitor) const

Executes a given function for every line segment in this node's sub-tree.

The function takes two Point arguments. These arguments will be filled in with the higher-order node (closer to the root) first, and the downtree node (closer to the leaves) as the second argument. The segment from this node's parent to this node itself is not included. The order in which the segments are visited is depth-first.

Parameters
visitorA function to execute for every branch in the node's sub- tree.
85{
86 for (const auto& node : m_children) {
87 assert(node->m_parent.lock() == shared_from_this());
88 visitor(m_p, node->m_p);
89 node->visitBranches(visitor);
90 }
91}

References m_children, and m_p.

◆ visitNodes()

void Slic3r::FillLightning::Node::visitNodes ( const std::function< void(NodeSPtr)> & visitor)

Execute a given function for every node in this node's sub-tree.

The visitor function takes a node as input. This node is not const, so this can be used to change the tree. Nodes are visited in depth-first order. This node itself is visited as well (pre-order).

Parameters
visitorA function to execute for every node in this node's sub- tree.
95{
96 visitor(shared_from_this());
97 for (const auto& node : m_children) {
98 assert(node->m_parent.lock() == shared_from_this());
99 node->visitNodes(visitor);
100 }
101}

References m_children.

◆ get_extents [1/2]

BoundingBox get_extents ( const NodeSPtr & root_node)
friend
296{
297 BoundingBox bbox;
298 for (const NodeSPtr &children : root_node->m_children)
299 bbox.merge(get_extents(children));
300 bbox.merge(root_node->getLocation());
301 return bbox;
302}
friend BoundingBox get_extents(const NodeSPtr &root_node)
Definition TreeNode.hpp:295

References Slic3r::FillLightning::get_extents(), getLocation(), m_children, and Slic3r::BoundingBoxBase< PointType, APointsType >::merge().

◆ get_extents [2/2]

BoundingBox get_extents ( const std::vector< NodeSPtr > & tree_roots)
friend
305{
306 BoundingBox bbox;
307 for (const NodeSPtr &root_node : tree_roots)
308 bbox.merge(get_extents(root_node));
309 return bbox;
310}

References Slic3r::FillLightning::get_extents(), and Slic3r::BoundingBoxBase< PointType, APointsType >::merge().

Member Data Documentation

◆ m_children

◆ m_is_root

bool Slic3r::FillLightning::Node::m_is_root
protected

◆ m_last_grounding_location

std::optional<Point> Slic3r::FillLightning::Node::m_last_grounding_location
protected

◆ m_p

◆ m_parent

std::weak_ptr<Node> Slic3r::FillLightning::Node::m_parent
protected

Referenced by reroot(), and straighten().


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