Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::FillLightning::DistanceField Class Reference

#include <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< UnsupportedCellm_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.

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.
38 :
40 m_supporting_radius(radius),
41 m_unsupported_points_bbox(current_outlines_bbox)
42{
44 // Sample source polygons with a regular grid sampling pattern.
45 const BoundingBox overhang_bbox = get_extents(current_overhang);
46 for (const ExPolygon &expoly : union_ex(current_overhang)) {
47 const Points sampled_points = sample_grid_pattern(expoly, m_cell_size, overhang_bbox);
48 const size_t unsupported_points_prev_size = m_unsupported_points.size();
49 m_unsupported_points.resize(unsupported_points_prev_size + sampled_points.size());
50
51 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 {
52 for (size_t sp_idx = range.begin(); sp_idx < range.end(); ++sp_idx) {
53 const Point &sp = sampled_points[sp_idx];
54 // Find a squared distance to the source expolygon boundary.
55 double d2 = std::numeric_limits<double>::max();
56 for (size_t icontour = 0; icontour <= expoly.holes.size(); ++icontour) {
57 const Polygon &contour = icontour == 0 ? expoly.contour : expoly.holes[icontour - 1];
58 if (contour.size() > 2) {
59 Point prev = contour.points.back();
60 for (const Point &p2 : contour.points) {
61 d2 = std::min(d2, Line::distance_to_squared(sp, prev, p2));
62 prev = p2;
63 }
64 }
65 }
66 self.m_unsupported_points[unsupported_points_prev_size + sp_idx] = {sp, coord_t(std::sqrt(d2))};
67 assert(self.m_unsupported_points_bbox.contains(sp));
68 }
69 }); // end of parallel_for
70 }
71 std::stable_sort(m_unsupported_points.begin(), m_unsupported_points.end(), [&radius](const UnsupportedCell &a, const UnsupportedCell &b) {
72 constexpr coord_t prime_for_hash = 191;
73 return std::abs(b.dist_to_boundary - a.dist_to_boundary) > radius ?
74 a.dist_to_boundary < b.dist_to_boundary :
75 (PointHash{}(a.loc) % prime_for_hash) < (PointHash{}(b.loc) % prime_for_hash);
76 });
77
79 std::fill(m_unsupported_points_erased.begin(), m_unsupported_points_erased.end(), false);
80
81 m_unsupported_points_grid.initialize(m_unsupported_points, [&self = std::as_const(*this)](const Point &p) -> Point { return self.to_grid_point(p); });
82
83 // Because the distance between two points is at least one axis equal to m_cell_size, every cell
84 // in m_unsupported_points_grid contains exactly one point.
86
87#ifdef LIGHTNING_DISTANCE_FIELD_DEBUG_OUTPUT
88 {
89 static int iRun = 0;
90 export_distance_field_to_svg(debug_out_path("FillLightning-DistanceField-%d.svg", iRun++), current_outline, current_overhang, m_unsupported_points);
91 }
92#endif
93}
void initialize(const std::vector< UnsupportedCell > &unsupported_points, const std::function< Point(const Point &)> &map_cell_to_grid)
Definition DistanceField.hpp:114
size_t size() const
Definition DistanceField.hpp:138
std::vector< UnsupportedCell > m_unsupported_points
Definition DistanceField.hpp:97
UnsupportedPointsGrid m_unsupported_points_grid
Definition DistanceField.hpp:186
coord_t m_supporting_radius
Definition DistanceField.hpp:80
std::vector< bool > m_unsupported_points_erased
Definition DistanceField.hpp:98
int64_t m_supporting_radius2
Definition DistanceField.hpp:81
coord_t m_cell_size
Definition DistanceField.hpp:74
const BoundingBox m_unsupported_points_bbox
Definition DistanceField.hpp:103
BoundingBox get_extents(const NodeSPtr &root_node)
Definition TreeNode.hpp:284
constexpr coord_t radius_per_cell_size
Definition DistanceField.cpp:17
std::string debug_out_path(const char *name,...)
Definition utils.cpp:218
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, ClipperLib::PolyFillType fill_type)
Definition ClipperUtils.cpp:774
auto range(Cont &&cont)
Definition libslic3r.h:356
constexpr T sqr(T x)
Definition libslic3r.h:258
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing, const BoundingBox &global_bounding_box)
Definition FillRectilinear.cpp:3062
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:58
Kernel::Point_2 Point
Definition point_areas.cpp:20
__int64 int64_t
Definition unistd.h:76

References Slic3r::FillLightning::get_extents(), m_cell_size, m_supporting_radius2, m_unsupported_points, 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.

198 {
200 }
PointType min
Definition BoundingBox.hpp:16

References m_cell_size, m_unsupported_points_bbox, and Slic3r::BoundingBoxBase< PointType, APointsType >::min.

◆ to_grid_point()

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

Maps the point to the grid coordinates.

191 {
192 return (point - m_unsupported_points_bbox.min) / m_cell_size;
193 }

References m_cell_size, m_unsupported_points_bbox, and Slic3r::BoundingBoxBase< PointType, APointsType >::min.

◆ 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.
44 {
45 for (size_t point_idx = start_idx; point_idx < m_unsupported_points.size(); ++point_idx) {
46 if (!m_unsupported_points_erased[point_idx]) {
47 *out_unsupported_cell_idx = point_idx;
48 *out_unsupported_location = m_unsupported_points[point_idx].loc;
49 return true;
50 }
51 }
52
53 return false;
54 }

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.
96{
97 Vec2d v = (added_leaf - to_node).cast<double>();
98 auto l2 = v.squaredNorm();
99 Vec2d extent = Vec2d(-v.y(), v.x()) * m_supporting_radius / sqrt(l2);
100
101 BoundingBox grid;
102 {
104 Point iextent(extent.cast<coord_t>());
105 grid = BoundingBox(added_leaf - diagonal, added_leaf + diagonal);
106 grid.merge(to_node - iextent);
107 grid.merge(to_node + iextent);
108 grid.merge(added_leaf - iextent);
109 grid.merge(added_leaf + iextent);
110
111 // Clip grid by m_unsupported_points_bbox. Mainly to ensure that grid.min is a non-negative value.
112 grid.min.x() = std::max(grid.min.x(), m_unsupported_points_bbox.min.x());
113 grid.min.y() = std::max(grid.min.y(), m_unsupported_points_bbox.min.y());
114 grid.max.x() = std::min(grid.max.x(), m_unsupported_points_bbox.max.x());
115 grid.max.y() = std::min(grid.max.y(), m_unsupported_points_bbox.max.y());
116
117 grid.min = this->to_grid_point(grid.min);
118 grid.max = this->to_grid_point(grid.max);
119 }
120
121 Point grid_addr;
122 Point grid_loc;
123 for (grid_addr.y() = grid.min.y(); grid_addr.y() <= grid.max.y(); ++grid_addr.y()) {
124 for (grid_addr.x() = grid.min.x(); grid_addr.x() <= grid.max.x(); ++grid_addr.x()) {
125 grid_loc = this->from_grid_point(grid_addr);
126 // Test inside a circle at the new leaf.
127 if ((grid_loc - added_leaf).cast<int64_t>().squaredNorm() > m_supporting_radius2) {
128 // Not inside a circle at the end of the new leaf.
129 // Test inside a rotated rectangle.
130 Vec2d vx = (grid_loc - to_node).cast<double>();
131 double d = v.dot(vx);
132 if (d >= 0 && d <= l2) {
133 d = extent.dot(vx);
134 if (d < -1. || d > 1.)
135 // Not inside a rotated rectangle.
136 continue;
137 }
138 }
139 // Inside a circle at the end of the new leaf, or inside a rotated rectangle.
140 // Remove unsupported leafs at this grid location.
141 if (const size_t cell_idx = m_unsupported_points_grid.find_cell_idx(grid_addr); cell_idx != std::numeric_limits<size_t>::max()) {
142 const UnsupportedCell &cell = m_unsupported_points[cell_idx];
143 if ((cell.loc - added_leaf).cast<int64_t>().squaredNorm() <= m_supporting_radius2) {
144 m_unsupported_points_erased[cell_idx] = true;
146 }
147 }
148 }
149 }
150}
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
Definition ArrayCwiseUnaryOps.h:152
PointType max
Definition BoundingBox.hpp:17
void mark_erased(const Point &grid_addr)
Definition DistanceField.hpp:153
size_t find_cell_idx(const Point &grid_addr)
Definition DistanceField.hpp:140
Point from_grid_point(const Point &point) const
Definition DistanceField.hpp:198
Point to_grid_point(const Point &point) const
Definition DistanceField.hpp:191
int32_t coord_t
Definition libslic3r.h:39
T l2(const boost::geometry::model::d2::point_xy< T > &v)
Definition ExtrusionSimulator.cpp:166
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:51
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:125

References Slic3r::grid(), Slic3r::l2(), Slic3r::FillLightning::DistanceField::UnsupportedCell::loc, and sqrt().

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

+ 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.

◆ m_supporting_radius2

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

Referenced by DistanceField().

◆ 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(), and tryGetNextPoint().

◆ 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 from_grid_point(), and to_grid_point().

◆ m_unsupported_points_erased

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

Referenced by tryGetNextPoint().

◆ m_unsupported_points_grid

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

The documentation for this class was generated from the following files: