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

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

Collaboration diagram for Slic3r::FillLightning::DistanceField:

Classes

struct  UnsupportedCell
class  UnsupportedPointsGrid

Public Member Functions

 DistanceField (const coord_t &radius, const Polygons &current_outline, const BoundingBox &current_outlines_bbox, const Polygons &current_overhang)
bool tryGetNextPoint (Point *out_unsupported_location, size_t *out_unsupported_cell_idx, const size_t start_idx=0) const
void update (const Point &to_node, const Point &added_leaf)

Protected Member Functions

Point to_grid_point (const Point &point) const
Point from_grid_point (const Point &point) const

Protected Attributes

coord_t m_cell_size
coord_t m_supporting_radius
int64_t m_supporting_radius2
std::vector< UnsupportedCell > m_unsupported_points
std::vector< bool > m_unsupported_points_erased
const BoundingBox m_unsupported_points_bbox
UnsupportedPointsGrid m_unsupported_points_grid

Detailed Description

2D field that maintains locations which need to be supported for Lightning Infill.

This field contains a set of "cells", spaced out in a grid. Each cell maintains how far it is removed from the edge, which is used to determine how it gets supported by Lightning Infill.


Class Documentation

◆ Slic3r::FillLightning::DistanceField::UnsupportedCell

struct Slic3r::FillLightning::DistanceField::UnsupportedCell

Represents a small discrete area of infill that needs to be supported.

Collaboration diagram for Slic3r::FillLightning::DistanceField::UnsupportedCell:
Class Members
coord_t dist_to_boundary
Point loc

Constructor & Destructor Documentation

◆ DistanceField()

Slic3r::FillLightning::DistanceField::DistanceField ( const coord_t & radius,
const Polygons & current_outline,
const BoundingBox & current_outlines_bbox,
const Polygons & current_overhang )

Construct a new field to calculate Lightning Infill with.

Parameters
radiusThe radius of influence that an infill line is expected to support in the layer above.
current_outlineThe total infill area on this layer.
current_overhangThe overhang that needs to be supported on this layer.
52 :
54 m_supporting_radius(radius),
55 m_unsupported_points_bbox(current_outlines_bbox)
56{
57 m_supporting_radius2 = Slic3r::sqr(int64_t(radius));
58 // Sample source polygons with a regular grid sampling pattern.
59 const BoundingBox overhang_bbox = get_extents(current_overhang);
60 ExPolygons expolys = offset2_ex(union_ex(current_overhang), -m_cell_size / 2, m_cell_size / 2); // remove dangling lines which causes sample_grid_pattern crash (fails the OUTER_LOW assertions)
61 for (const ExPolygon &expoly : expolys) {
62 const Points sampled_points = sample_grid_pattern(expoly, m_cell_size, overhang_bbox);
63 const size_t unsupported_points_prev_size = m_unsupported_points.size();
64 m_unsupported_points.resize(unsupported_points_prev_size + sampled_points.size());
65
66 tbb::parallel_for(tbb::blocked_range<size_t>(0, sampled_points.size()), [&self = *this, &expoly = std::as_const(expoly), &sampled_points = std::as_const(sampled_points), &unsupported_points_prev_size = std::as_const(unsupported_points_prev_size)](const tbb::blocked_range<size_t> &range) -> void {
67 for (size_t sp_idx = range.begin(); sp_idx < range.end(); ++sp_idx) {
68 const Point &sp = sampled_points[sp_idx];
69 // Find a squared distance to the source expolygon boundary.
70 double d2 = std::numeric_limits<double>::max();
71 for (size_t icontour = 0; icontour <= expoly.holes.size(); ++icontour) {
72 const Polygon &contour = icontour == 0 ? expoly.contour : expoly.holes[icontour - 1];
73 if (contour.size() > 2) {
74 Point prev = contour.points.back();
75 for (const Point &p2 : contour.points) {
76 d2 = std::min(d2, Line::distance_to_squared(sp, prev, p2));
77 prev = p2;
78 }
79 }
80 }
81 self.m_unsupported_points[unsupported_points_prev_size + sp_idx] = {sp, coord_t(std::sqrt(d2))};
82 assert(self.m_unsupported_points_bbox.contains(sp));
83 }
84 }); // end of parallel_for
85 }
86 std::stable_sort(m_unsupported_points.begin(), m_unsupported_points.end(), [&radius](const UnsupportedCell &a, const UnsupportedCell &b) {
87 constexpr coord_t prime_for_hash = 191;
88 return std::abs(b.dist_to_boundary - a.dist_to_boundary) > radius ?
89 a.dist_to_boundary < b.dist_to_boundary :
90 (PointHash{}(a.loc) % prime_for_hash) < (PointHash{}(b.loc) % prime_for_hash);
91 });
92
94 std::fill(m_unsupported_points_erased.begin(), m_unsupported_points_erased.end(), false);
95
96 m_unsupported_points_grid.initialize(m_unsupported_points, [&self = std::as_const(*this)](const Point &p) -> Point { return self.to_grid_point(p); });
97
98 // Because the distance between two points is at least one axis equal to m_cell_size, every cell
99 // in m_unsupported_points_grid contains exactly one point.
100 assert(m_unsupported_points.size() == m_unsupported_points_grid.size());
101
102#ifdef LIGHTNING_DISTANCE_FIELD_DEBUG_OUTPUT
103 {
104 static int iRun = 0;
105 export_distance_field_to_svg(debug_out_path("FillLightning-DistanceField-%d.svg", iRun++), current_outline, current_overhang, m_unsupported_points);
106 }
107#endif
108}
std::vector< UnsupportedCell > m_unsupported_points
Definition DistanceField.hpp:104
UnsupportedPointsGrid m_unsupported_points_grid
Definition DistanceField.hpp:193
coord_t m_supporting_radius
Definition DistanceField.hpp:87
std::vector< bool > m_unsupported_points_erased
Definition DistanceField.hpp:105
int64_t m_supporting_radius2
Definition DistanceField.hpp:88
coord_t m_cell_size
Definition DistanceField.hpp:81
const BoundingBox m_unsupported_points_bbox
Definition DistanceField.hpp:110
BoundingBox get_extents(const NodeSPtr &root_node)
Definition TreeNode.hpp:295
constexpr coord_t radius_per_cell_size
Definition DistanceField.cpp:31
std::string debug_out_path(const char *name,...)
Definition utils.cpp:382
std::vector< ExPolygon > ExPolygons
Definition ExPolygon.hpp:20
auto range(Cont &&cont)
Definition libslic3r.h:405
constexpr T sqr(T x)
Definition libslic3r.h:301
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, PolyFillType fill_type)
Definition ClipperUtils.cpp:1011
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing, const BoundingBox &global_bounding_box)
Definition FillRectilinear.cpp:3741
ExPolygons offset2_ex(const ExPolygons &expolygons, const float delta1, const float delta2, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:652

References Slic3r::FillLightning::get_extents(), m_cell_size, m_supporting_radius, m_supporting_radius2, m_unsupported_points, m_unsupported_points_bbox, Slic3r::offset2_ex(), Slic3r::FillLightning::radius_per_cell_size, Slic3r::range(), Slic3r::sample_grid_pattern(), Slic3r::sqr(), and Slic3r::union_ex().

Here is the call graph for this function:

Member Function Documentation

◆ from_grid_point()

Point Slic3r::FillLightning::DistanceField::from_grid_point ( const Point & point) const
inlineprotected

Maps the point to the grid coordinates.

205 {
206 return point * m_cell_size + m_unsupported_points_bbox.min;
207 }

References m_cell_size, and m_unsupported_points_bbox.

Referenced by update().

Here is the caller graph for this function:

◆ to_grid_point()

Point Slic3r::FillLightning::DistanceField::to_grid_point ( const Point & point) const
inlineprotected

Maps the point to the grid coordinates.

198 {
199 return (point - m_unsupported_points_bbox.min) / m_cell_size;
200 }

References m_cell_size, and m_unsupported_points_bbox.

Referenced by update().

Here is the caller graph for this function:

◆ tryGetNextPoint()

bool Slic3r::FillLightning::DistanceField::tryGetNextPoint ( Point * out_unsupported_location,
size_t * out_unsupported_cell_idx,
const size_t start_idx = 0 ) const
inline

Gets the next unsupported location to be supported by a new branch.

Parameters
pOutput variable for the next point to support.
Returns
true if successful, or false if there are no more points to consider.
51 {
52 for (size_t point_idx = start_idx; point_idx < m_unsupported_points.size(); ++point_idx) {
53 if (!m_unsupported_points_erased[point_idx]) {
54 *out_unsupported_cell_idx = point_idx;
55 *out_unsupported_location = m_unsupported_points[point_idx].loc;
56 return true;
57 }
58 }
59
60 return false;
61 }

References m_unsupported_points, and m_unsupported_points_erased.

Referenced by Slic3r::FillLightning::Layer::generateNewTrees().

Here is the caller graph for this function:

◆ update()

void Slic3r::FillLightning::DistanceField::update ( const Point & to_node,
const Point & added_leaf )

Update the distance field with a newly added branch.

The branch is a line extending from to_node to added_leaf . This function updates the grid cells so that the distance field knows how far off it is from being supported by the current pattern. Grid points are updated with sampling points spaced out by the supporting radius along the line.

Parameters
to_nodeThe node endpoint of the newly added branch.
added_leafThe location of the leaf of the newly added branch, drawing a straight line to the node.
111{
112 Vec2d v = (added_leaf - to_node).cast<double>();
113 auto l2 = v.squaredNorm();
114 Vec2d extent = Vec2d(-v.y(), v.x()) * m_supporting_radius / sqrt(l2);
115
116 BoundingBox grid;
117 {
119 Point iextent(extent.cast<coord_t>());
120 grid = BoundingBox(added_leaf - diagonal, added_leaf + diagonal);
121 grid.merge(to_node - iextent);
122 grid.merge(to_node + iextent);
123 grid.merge(added_leaf - iextent);
124 grid.merge(added_leaf + iextent);
125
126 // Clip grid by m_unsupported_points_bbox. Mainly to ensure that grid.min is a non-negative value.
127 grid.min.x() = std::max(grid.min.x(), m_unsupported_points_bbox.min.x());
128 grid.min.y() = std::max(grid.min.y(), m_unsupported_points_bbox.min.y());
129 grid.max.x() = std::min(grid.max.x(), m_unsupported_points_bbox.max.x());
130 grid.max.y() = std::min(grid.max.y(), m_unsupported_points_bbox.max.y());
131
132 grid.min = this->to_grid_point(grid.min);
133 grid.max = this->to_grid_point(grid.max);
134 }
135
136 Point grid_addr;
137 Point grid_loc;
138 for (grid_addr.y() = grid.min.y(); grid_addr.y() <= grid.max.y(); ++grid_addr.y()) {
139 for (grid_addr.x() = grid.min.x(); grid_addr.x() <= grid.max.x(); ++grid_addr.x()) {
140 grid_loc = this->from_grid_point(grid_addr);
141 // Test inside a circle at the new leaf.
142 if ((grid_loc - added_leaf).cast<int64_t>().squaredNorm() > m_supporting_radius2) {
143 // Not inside a circle at the end of the new leaf.
144 // Test inside a rotated rectangle.
145 Vec2d vx = (grid_loc - to_node).cast<double>();
146 double d = v.dot(vx);
147 if (d >= 0 && d <= l2) {
148 d = extent.dot(vx);
149 if (d < -1. || d > 1.)
150 // Not inside a rotated rectangle.
151 continue;
152 }
153 }
154 // Inside a circle at the end of the new leaf, or inside a rotated rectangle.
155 // Remove unsupported leafs at this grid location.
156 if (const size_t cell_idx = m_unsupported_points_grid.find_cell_idx(grid_addr); cell_idx != std::numeric_limits<size_t>::max()) {
157 const UnsupportedCell &cell = m_unsupported_points[cell_idx];
158 if ((cell.loc - added_leaf).cast<int64_t>().squaredNorm() <= m_supporting_radius2) {
159 m_unsupported_points_erased[cell_idx] = true;
160 m_unsupported_points_grid.mark_erased(grid_addr);
161 }
162 }
163 }
164 }
165}
Point from_grid_point(const Point &point) const
Definition DistanceField.hpp:205
Point to_grid_point(const Point &point) const
Definition DistanceField.hpp:198
int64_t coord_t
Definition libslic3r.h:48
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
T l2(const boost::geometry::model::d2::point_xy< T > &v)
Definition ExtrusionSimulator.cpp:177
std::vector< ArithmeticOnly< T > > grid(const T &start, const T &stop, const T &stride)
A set of equidistant values starting from 'start' (inclusive), ending in the closest multiple of 'str...
Definition MTUtils.hpp:127
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299

References Slic3r::cast(), from_grid_point(), Slic3r::grid(), Slic3r::l2(), Slic3r::FillLightning::DistanceField::UnsupportedCell::loc, m_supporting_radius, m_supporting_radius2, m_unsupported_points, m_unsupported_points_bbox, m_unsupported_points_erased, m_unsupported_points_grid, to_grid_point(), and update().

Referenced by Slic3r::FillLightning::Layer::generateNewTrees(), and update().

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

Member Data Documentation

◆ m_cell_size

coord_t Slic3r::FillLightning::DistanceField::m_cell_size
protected

Spacing between grid points to consider supporting.

Referenced by DistanceField(), from_grid_point(), and to_grid_point().

◆ m_supporting_radius

coord_t Slic3r::FillLightning::DistanceField::m_supporting_radius
protected

The radius of the area of the layer above supported by a point on a branch of a tree.

Referenced by DistanceField(), and update().

◆ m_supporting_radius2

int64_t Slic3r::FillLightning::DistanceField::m_supporting_radius2
protected

Referenced by DistanceField(), and update().

◆ m_unsupported_points

std::vector<UnsupportedCell> Slic3r::FillLightning::DistanceField::m_unsupported_points
protected

Cells which still need to be supported at some point.

Referenced by DistanceField(), tryGetNextPoint(), and update().

◆ m_unsupported_points_bbox

const BoundingBox Slic3r::FillLightning::DistanceField::m_unsupported_points_bbox
protected

BoundingBox of all points in m_unsupported_points. Used for mapping of sign integer numbers to positive integer numbers.

Referenced by DistanceField(), from_grid_point(), to_grid_point(), and update().

◆ m_unsupported_points_erased

std::vector<bool> Slic3r::FillLightning::DistanceField::m_unsupported_points_erased
protected

Referenced by tryGetNextPoint(), and update().

◆ m_unsupported_points_grid

UnsupportedPointsGrid Slic3r::FillLightning::DistanceField::m_unsupported_points_grid
protected

Referenced by update().


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