OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::Algorithm Namespace Reference

Classes

struct  SplitLineJunction
struct  RegionExpansionParameters
struct  WaveSeed
struct  RegionExpansion
struct  RegionExpansionEx

Typedefs

using SplitNode = std::vector<ClipperZUtils::ZPath*>
using SplittedLine = std::vector<SplitLineJunction>
using AABBTreeBBoxes = AABBTreeIndirect::Tree<2, coord_t>
using WaveSeeds = std::vector<WaveSeed>

Functions

static void cb_split_line (const ClipperZUtils::ZPoint &e1bot, const ClipperZUtils::ZPoint &e1top, const ClipperZUtils::ZPoint &e2bot, const ClipperZUtils::ZPoint &e2top, ClipperZUtils::ZPoint &pt)
static bool is_src (const ClipperZUtils::ZPoint &p)
static bool is_clip (const ClipperZUtils::ZPoint &p)
static bool is_new (const ClipperZUtils::ZPoint &p)
static size_t to_src_idx (const ClipperZUtils::ZPoint &p)
static Point to_point (const ClipperZUtils::ZPoint &p)
static bool point_on_line (const Point &p, const Line &l)
SplittedLine do_split_line (const ClipperZUtils::ZPath &path, const ExPolygons &clip, bool closed)
template<class PathType>
SplittedLine split_line (const PathType &path, const ExPolygons &clip, bool closed)
double clipper_round_offset_error (double offset, double arc_tolerance)
static ClipperZUtils::ZPaths expolygons_to_zpaths_expanded_opened (const ExPolygons &src, const float expansion, coord_t &base_idx)
static void merge_splits (ClipperZUtils::ZPaths &paths, std::vector< std::pair< ClipperZUtils::ZPoint, int > > &splits)
static AABBTreeBBoxes build_aabb_tree_over_expolygons (const ExPolygons &expolygons)
static int sample_in_expolygons (const AABBTreeBBoxes &aabb_tree, const ExPolygons &expolygons, const Point &sample)
std::vector< WaveSeed > wave_seeds (const ExPolygons &src, const ExPolygons &boundary, float tiny_expansion, bool sorted)
static Polygons wavefront_initial (const VecOfPoints &polylines, float offset, double arc_tolerance)
static Polygons wavefront_step (const Polygons &polygons, float offset, double arc_tolerance)
static Polygons wavefront_clip (const Polygons &wavefront, const Polygons &clipping)
static Polygons propagate_wave_from_boundary (const VecOfPoints &seed, const ExPolygon &boundary, const float initial_step, const float other_step, const size_t num_other_steps, const float max_inflation, const double arc_tolerance)
std::vector< RegionExpansion > propagate_waves (const WaveSeeds &seeds, const ExPolygons &boundary, const RegionExpansionParameters &params)
std::vector< RegionExpansion > propagate_waves (const ExPolygons &src, const ExPolygons &boundary, const RegionExpansionParameters &params)
std::vector< RegionExpansion > propagate_waves (const ExPolygons &src, const ExPolygons &boundary, float expansion, float expansion_step, size_t max_nr_steps)
std::vector< RegionExpansionEx > propagate_waves_ex (const WaveSeeds &seeds, const ExPolygons &boundary, const RegionExpansionParameters &params)
std::vector< RegionExpansionEx > propagate_waves_ex (const ExPolygons &src, const ExPolygons &boundary, float full_expansion, float expansion_step, size_t max_nr_expansion_steps)
std::vector< Polygons > expand_expolygons (const ExPolygons &src, const ExPolygons &boundary, float expansion, float expansion_step, size_t max_nr_steps)
std::vector< ExPolygon > merge_expansions_into_expolygons (ExPolygons &&src, std::vector< RegionExpansion > &&expanded)
std::vector< ExPolygon > expand_merge_expolygons (ExPolygons &&src, const ExPolygons &boundary, const RegionExpansionParameters &params)
bool lower_by_boundary_and_src (const WaveSeed &l, const WaveSeed &r)
bool lower_by_src_and_boundary (const WaveSeed &l, const WaveSeed &r)

Variables

static constexpr auto CLIP_IDX = std::numeric_limits<coord_t>::max()

Class Documentation

◆ Slic3r::Algorithm::WaveSeed

struct Slic3r::Algorithm::WaveSeed
Collaboration diagram for Slic3r::Algorithm::WaveSeed:
Class Members
uint32_t boundary
Points path
uint32_t src

◆ Slic3r::Algorithm::RegionExpansion

struct Slic3r::Algorithm::RegionExpansion
Collaboration diagram for Slic3r::Algorithm::RegionExpansion:
Class Members
uint32_t boundary_id
Polygon polygon
uint32_t src_id

◆ Slic3r::Algorithm::RegionExpansionEx

struct Slic3r::Algorithm::RegionExpansionEx
Collaboration diagram for Slic3r::Algorithm::RegionExpansionEx:
Class Members
uint32_t boundary_id
ExPolygon expolygon
uint32_t src_id

Typedef Documentation

◆ AABBTreeBBoxes

◆ SplitNode

◆ SplittedLine

◆ WaveSeeds

using Slic3r::Algorithm::WaveSeeds = std::vector<WaveSeed>

Function Documentation

◆ build_aabb_tree_over_expolygons()

AABBTreeBBoxes Slic3r::Algorithm::build_aabb_tree_over_expolygons ( const ExPolygons & expolygons)
static
169{
170 // Calculate bounding boxes of internal slices.
171 std::vector<AABBTreeIndirect::BoundingBoxWrapper> bboxes;
172 bboxes.reserve(expolygons.size());
173 for (size_t i = 0; i < expolygons.size(); ++ i)
174 bboxes.emplace_back(i, get_extents(expolygons[i].contour));
175 // Build AABB tree over bounding boxes of boundary expolygons.
176 AABBTreeBBoxes out;
177 out.build_modify_input(bboxes);
178 return out;
179}
void build_modify_input(std::vector< SourceNode > &input)
Definition AABBTreeIndirect.hpp:98
AABBTreeIndirect::Tree< 2, coord_t > AABBTreeBBoxes
Definition RegionExpansion.cpp:166
BoundingBox get_extents(const ExPolygonsWithIds &e)
Definition Emboss.cpp:1374
const Polygon & contour(const ExPolygon &p)
Definition AGGRaster.hpp:30

References Slic3r::AABBTreeIndirect::Tree< ANumDimensions, ACoordType >::build_modify_input(), Slic3r::contour(), and Slic3r::get_extents().

Referenced by merge_expansions_into_expolygons(), and wave_seeds().

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

◆ cb_split_line()

void Slic3r::Algorithm::cb_split_line ( const ClipperZUtils::ZPoint & e1bot,
const ClipperZUtils::ZPoint & e1top,
const ClipperZUtils::ZPoint & e2bot,
const ClipperZUtils::ZPoint & e2top,
ClipperZUtils::ZPoint & pt )
static
36{
37 coord_t zs[4]{e1bot.z(), e1top.z(), e2bot.z(), e2top.z()};
38 std::sort(zs, zs + 4);
39 pt.z() = -(zs[0] + 1);
40}
int64_t coord_t
Definition libslic3r.h:48

Referenced by do_split_line().

Here is the caller graph for this function:

◆ clipper_round_offset_error()

double Slic3r::Algorithm::clipper_round_offset_error ( double offset,
double arc_tolerance )
inline
30{
31 static constexpr const double def_arc_tolerance = 0.25;
32 const double y =
33 arc_tolerance <= 0 ?
34 def_arc_tolerance :
35 arc_tolerance > offset * def_arc_tolerance ?
36 offset * def_arc_tolerance :
37 arc_tolerance;
38 double steps = std::min(M_PI / std::acos(1. - y / offset), offset * M_PI);
39 return offset * (1. - cos(M_PI / steps));
40}
#define M_PI
Definition ExtrusionSimulator.cpp:31
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582

References M_PI, and Slic3r::offset().

Here is the call graph for this function:

◆ do_split_line()

SplittedLine Slic3r::Algorithm::do_split_line ( const ClipperZUtils::ZPath & path,
const ExPolygons & clip,
bool closed )
77{
78 assert(path.size() > 1);
79#ifdef DEBUG_SPLIT_LINE
80 const auto dbg_path_points = ClipperZUtils::from_zpath<false>(path);
81 BoundingBox dbg_bbox = get_extents(clip);
82 dbg_bbox.merge(get_extents(dbg_path_points));
83 dbg_bbox.offset(scale_(1.));
84 const std::uint32_t dbg_id = g_dbg_id++;
85 {
86 ::Slic3r::SVG svg(debug_out_path("do_split_line_%d_input.svg", dbg_id).c_str(), dbg_bbox);
87 svg.draw(clip, "red", 0.5);
88 svg.draw_outline(clip, "red");
89 svg.draw(Polyline{dbg_path_points});
90 svg.draw(dbg_path_points);
91 svg.Close();
92 }
93#endif
94
95 ClipperZUtils::ZPaths intersections;
96 // Perform an intersection
97 {
98 // Convert clip polygon to closed contours
99 ClipperZUtils::ZPaths clip_path;
100 for (const auto& exp : clip) {
101 clip_path.emplace_back(ClipperZUtils::to_zpath<false>(exp.contour.points, CLIP_IDX));
102 for (const Polygon& hole : exp.holes)
103 clip_path.emplace_back(ClipperZUtils::to_zpath<false>(hole.points, CLIP_IDX));
104 }
105
106 intersections = ClipperZUtils::clip_zpaths(ctIntersection, ClipperZUtils::ZPaths{ path }, true, clip_path, cb_split_line, true);
107 }
108 if (intersections.empty()) {
109 return {};
110 }
111
112#ifdef DEBUG_SPLIT_LINE
113 {
114 int i = 0;
115 for (const auto& segment : intersections) {
116 ::Slic3r::SVG svg(debug_out_path("do_split_line_%d_seg_%d.svg", dbg_id, i).c_str(), dbg_bbox);
117 svg.draw(clip, "red", 0.5);
118 svg.draw_outline(clip, "red");
119 const auto segment_points = ClipperZUtils::from_zpath<false>(segment);
120 svg.draw(Polyline{segment_points});
121 for (const ClipperZUtils::ZPoint& p : segment) {
122 const auto z = p.z();
123 if (is_new(p)) {
124 svg.draw(to_point(p), "yellow");
125 } else if (is_clip(p)) {
126 svg.draw(to_point(p), "red");
127 } else {
128 svg.draw(to_point(p), "black");
129 }
130 }
131 svg.Close();
132 i++;
133 }
134 }
135#endif
136
137 // Connect the intersection back to the remaining loop
138 std::vector<SplitNode> split_chain;
139 {
140 // AABBTree over source paths.
141 // Only built if necessary, that is if any of the clipped segment has first point came from clip polygon,
142 // and we need to find out which source edge that point came from.
143 AABBTreeLines::LinesDistancer<Line> aabb_tree;
144 const auto resolve_clip_point = [&path, &aabb_tree](ClipperZUtils::ZPoint& zp) {
145 if (!is_clip(zp)) {
146 return;
147 }
148
149 if (aabb_tree.get_lines().empty()) {
150 Lines lines;
151 lines.reserve(path.size() - 1);
152 for (auto it = path.begin() + 1; it != path.end(); ++it) {
153 lines.emplace_back(to_point(it[-1]), to_point(*it));
154 }
155 aabb_tree = AABBTreeLines::LinesDistancer(lines);
156 }
157
158 const Point p = to_point(zp);
159 const auto possible_edges = aabb_tree.all_lines_in_radius(p, SCALED_EPSILON);
160 assert(!possible_edges.empty());
161 for (const size_t l : possible_edges) {
162 // Check if the point is on the line
163 const Line line(to_point(path[l]), to_point(path[l + 1]));
164 if (p == line.a) {
165 zp.z() = path[l].z();
166 break;
167 }
168 if (p == line.b) {
169 zp.z() = path[l + 1].z();
170 break;
171 }
172 if (point_on_line(p, line)) {
173 zp.z() = -(path[l].z() + 1);
174 break;
175 }
176 }
177 if (is_clip(zp)) {
178 // Too bad! Couldn't find the src edge, so we just pick the first one and hope it works
179 zp.z() = -(path[possible_edges[0]].z() + 1);
180 }
181 };
182
183 split_chain.assign(path.size(), {});
184 for (ClipperZUtils::ZPath& segment : intersections) {
185 assert(segment.size() >= 2);
186 // Resolve all clip points
187 std::for_each(segment.begin(), segment.end(), resolve_clip_point);
188
189 // Ensure the point order in segment
190 std::sort(segment.begin(), segment.end(), [&path](const ClipperZUtils::ZPoint& a, const ClipperZUtils::ZPoint& b) -> bool {
191 if (is_new(a) && is_new(b) && a.z() == b.z()) {
192 // Make sure a point is closer to the src point than b
193 const auto src = to_point(path[-a.z() - 1]);
194 return (to_point(a) - src).squaredNorm() < (to_point(b) - src).squaredNorm();
195 }
196 const auto a_idx = to_src_idx(a);
197 const auto b_idx = to_src_idx(b);
198 if (a_idx == b_idx) {
199 // On same line, prefer the src point first
200 return is_src(a);
201 } else {
202 return a_idx < b_idx;
203 }
204 });
205
206 // Chain segment back to the original path
207 ClipperZUtils::ZPoint& front = segment.front();
208 const ClipperZUtils::ZPoint* previous_src_point = nullptr;
209 if (is_src(front)) {
210 // The segment starts with a point from src path, which means apart from the last point,
211 // all other points on this segment should come from the src path or the clip polygon
212
213 // Connect the segment to the src path
214 auto& node = split_chain[front.z()];
215 node.insert(node.begin(), &segment);
216
217 previous_src_point = &front;
218 } else if (is_new(front)) {
219 const auto id = -front.z() - 1; // Get the src path index
220 const ClipperZUtils::ZPoint& src_p = path[id]; // Get the corresponding src point
221 const auto dist2 = (front - src_p).block<2, 1>(0,0).squaredNorm(); // Distance between the src point and current point
222 // Find the place on the src line that current point should lie on
223 auto& node = split_chain[id];
224 auto it = std::find_if(node.begin(), node.end(), [dist2, &src_p](const ClipperZUtils::ZPath* p) {
225 const ClipperZUtils::ZPoint& p_front = p->front();
226 if (is_src(p_front)) {
227 return false;
228 }
229
230 const auto dist2_2 = (p_front - src_p).block<2, 1>(0, 0).squaredNorm();
231 return dist2_2 > dist2;
232 });
233 // Insert this split
234 node.insert(it, &segment);
235
236 previous_src_point = &src_p;
237 } else {
238 assert(false);
239 }
240
241 // Once we figured out the start point, we can then normalize the remaining points on the segment
242 for (ClipperZUtils::ZPoint& p : segment) {
243 assert(!is_new(p) || p == front || p == segment.back()); // Only the first and last point can be a new intersection
244 if (is_src(p)) {
245 previous_src_point = &p;
246 } else if (is_clip(p)) {
247 // Treat point from clip polygon as new point
248 p.z() = -(previous_src_point->z() + 1);
249 }
250 }
251 }
252 }
253
254 // Now we reconstruct the final path by connecting splits
255 SplittedLine result;
256 size_t idx = 0;
257 while (idx < split_chain.size()) {
258 const ClipperZUtils::ZPoint& p = path[idx];
259 const auto& node = split_chain[idx];
260 if (node.empty()) {
261 result.emplace_back(to_point(p), false, idx);
262 idx++;
263 } else {
264 if (!is_src(node.front()->front())) {
265 if (result.empty() || result.back().get_src_index() != to_src_idx(p)) {
266 //const auto& last = result.back();
267 //if (result.empty() || last.get_src_index() != to_src_idx(p)) {
268 result.emplace_back(to_point(p), false, idx);
269 }
270 }
271 for (const auto segment : node) {
272 for (const ClipperZUtils::ZPoint& sp : *segment) {
273 assert(!is_clip(sp));
274 result.emplace_back(to_point(sp), true, sp.z());
275 }
276 result.back().clipped = false; // Mark the end of the clipped line
277 }
278
279 // Determine the next start point
280 const auto back = result.back().src_idx;
281 if (back < 0) {
282 auto next_idx = -back - 1;
283 if (next_idx == idx) {
284 next_idx++;
285 } else if (split_chain[next_idx].empty()) {
286 next_idx++;
287 }
288 idx = next_idx;
289 } else {
290 result.pop_back();
291 idx = back;
292 }
293 }
294 }
295
296
297#ifdef DEBUG_SPLIT_LINE
298 {
299 ::Slic3r::SVG svg(debug_out_path("do_split_line_%d_result.svg", dbg_id).c_str(), dbg_bbox);
300 svg.draw(clip, "red", 0.5);
301 svg.draw_outline(clip, "red");
302 for (auto it = result.begin() + 1; it != result.end(); ++it) {
303 const auto& a = *(it - 1);
304 const auto& b = *it;
305 const bool clipped = a.clipped;
306 const Line l(a.p, b.p);
307 svg.draw(l, clipped ? "yellow" : "black");
308 }
309 svg.Close();
310 }
311#endif
312
313 if (closed) {
314 // Remove last point which was duplicated
315 result.pop_back();
316 }
317
318 return result;
319}
void merge(const PointType &point)
Definition BoundingBox.cpp:75
void offset(coordf_t delta)
Definition BoundingBox.cpp:209
Definition BoundingBox.hpp:212
Definition Polyline.hpp:25
Definition SVG.hpp:22
#define SCALED_EPSILON
Definition libslic3r.h:109
#define scale_(val)
Definition libslic3r.h:106
static bool is_src(const ClipperZUtils::ZPoint &p)
Definition LineSplit.cpp:42
static Point to_point(const ClipperZUtils::ZPoint &p)
Definition LineSplit.cpp:55
std::vector< SplitLineJunction > SplittedLine
Definition LineSplit.hpp:44
static size_t to_src_idx(const ClipperZUtils::ZPoint &p)
Definition LineSplit.cpp:45
static void cb_split_line(const ClipperZUtils::ZPoint &e1bot, const ClipperZUtils::ZPoint &e1top, const ClipperZUtils::ZPoint &e2bot, const ClipperZUtils::ZPoint &e2top, ClipperZUtils::ZPoint &pt)
Definition LineSplit.cpp:31
static bool point_on_line(const Point &p, const Line &l)
Definition LineSplit.cpp:60
static constexpr auto CLIP_IDX
Definition LineSplit.cpp:29
static bool is_clip(const ClipperZUtils::ZPoint &p)
Definition LineSplit.cpp:43
static bool is_new(const ClipperZUtils::ZPoint &p)
Definition LineSplit.cpp:44
std::vector< ZPath, PointsAllocator< ZPath > > ZPaths
Definition ClipperZUtils.hpp:25
ZPaths clip_zpaths(ClipType clip_type, const ZPaths &subject, bool subject_open, const ZPaths &clip, const ZFillCallback &zfill, bool preserve_collinear)
Definition ClipperZUtils.cpp:48
ZPoints ZPath
Definition ClipperZUtils.hpp:24
Points from_zpath(const ZPoints &path)
Definition ClipperZUtils.hpp:84
Vec3crd ZPoint
Definition ClipperZUtils.hpp:22
ZPath to_zpath(const Points &path, coord_t z)
Definition ClipperZUtils.hpp:38
void segment(CGALMesh &src, std::vector< CGALMesh > &dst, double smoothing_alpha=0.5, int segment_number=5)
Definition MeshBoolean.cpp:480
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
std::vector< Line > Lines
Definition Line.hpp:20
std::string debug_out_path(const char *name,...)
Definition utils.cpp:382
bool empty(const BoundingBoxBase< PointType, PointsType > &bb)
Definition BoundingBox.hpp:273
@ ctIntersection
Definition ClipperUtils.hpp:24

References Slic3r::Line::a, Slic3r::AABBTreeLines::LinesDistancer< LineType >::all_lines_in_radius(), Slic3r::Line::b, cb_split_line(), CLIP_IDX, Slic3r::ClipperZUtils::clip_zpaths(), Slic3r::SVG::Close(), Slic3r::ctIntersection, Slic3r::debug_out_path(), Slic3r::SVG::draw(), Slic3r::SVG::draw_outline(), Slic3r::ClipperZUtils::from_zpath(), Slic3r::get_extents(), Slic3r::AABBTreeLines::LinesDistancer< LineType >::get_lines(), is_clip(), is_new(), is_src(), Slic3r::BoundingBoxBase< PointType, APointsType >::merge(), Slic3r::BoundingBoxBase< PointType, APointsType >::offset(), point_on_line(), Slic3r::MultiPoint::points, scale_, SCALED_EPSILON, to_point(), to_src_idx(), and Slic3r::ClipperZUtils::to_zpath().

Referenced by split_line().

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

◆ expand_expolygons()

std::vector< Polygons > Slic3r::Algorithm::expand_expolygons ( const ExPolygons & src,
const ExPolygons & boundary,
float expansion,
float expansion_step,
size_t max_nr_steps )
507{
508 std::vector<Polygons> out(src.size(), Polygons{});
509 for (RegionExpansion &r : propagate_waves(src, boundary, expansion, expansion_step, max_nr_steps))
510 out[r.src_id].emplace_back(std::move(r.polygon));
511 return out;
512}
std::vector< RegionExpansion > propagate_waves(const WaveSeeds &seeds, const ExPolygons &boundary, const RegionExpansionParameters &params)
Definition RegionExpansion.cpp:421
Definition RegionExpansion.hpp:69
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22

References propagate_waves().

Here is the call graph for this function:

◆ expand_merge_expolygons()

std::vector< ExPolygon > Slic3r::Algorithm::expand_merge_expolygons ( ExPolygons && src,
const ExPolygons & boundary,
const RegionExpansionParameters & params )
568{
569 // expanded regions are sorted by boundary id and source id
570 std::vector<RegionExpansion> expanded = propagate_waves(src, boundary, params);
571 return merge_expansions_into_expolygons(std::move(src), std::move(expanded));
572}
std::vector< ExPolygon > merge_expansions_into_expolygons(ExPolygons &&src, std::vector< RegionExpansion > &&expanded)
Definition RegionExpansion.cpp:514

References merge_expansions_into_expolygons(), and propagate_waves().

Here is the call graph for this function:

◆ expolygons_to_zpaths_expanded_opened()

ClipperZUtils::ZPaths Slic3r::Algorithm::expolygons_to_zpaths_expanded_opened ( const ExPolygons & src,
const float expansion,
coord_t & base_idx )
static
94{
96 out.reserve(2 * std::accumulate(src.begin(), src.end(), size_t(0),
97 [](const size_t acc, const ExPolygon &expoly) { return acc + expoly.num_contours(); }));
98 for (const ExPolygon &expoly : src) {
99 for (size_t icontour = 0; icontour < expoly.num_contours(); ++ icontour) {
100 // Orient CCW, then grow the contour and shrink the holes. The output contours are CCW.
101 Polygon contour = expoly.contour_or_hole(icontour);
102 if (! contour.is_counter_clockwise())
103 contour.reverse();
104 for (const Polygon &expanded : offset(contour, icontour == 0 ? expansion : -expansion, jtSquare))
105 out.emplace_back(ClipperZUtils::to_zpath<true>(expanded.points, base_idx));
106 }
107 ++ base_idx;
108 }
109 return out;
110}
Definition ExPolygon.hpp:23
size_t num_contours() const
Definition ExPolygon.hpp:87
Polygon & contour_or_hole(size_t idx)
Definition ExPolygon.hpp:88
Definition Polygon.hpp:31
@ jtSquare
Definition ClipperUtils.hpp:21

References Slic3r::contour(), Slic3r::ExPolygon::contour_or_hole(), Slic3r::jtSquare, Slic3r::ExPolygon::num_contours(), Slic3r::offset(), and Slic3r::ClipperZUtils::to_zpath().

Referenced by wave_seeds().

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

◆ is_clip()

bool Slic3r::Algorithm::is_clip ( const ClipperZUtils::ZPoint & p)
static
43{ return p.z() == CLIP_IDX; }

References CLIP_IDX.

Referenced by do_split_line(), and to_src_idx().

Here is the caller graph for this function:

◆ is_new()

bool Slic3r::Algorithm::is_new ( const ClipperZUtils::ZPoint & p)
static
44{ return p.z() < 0; }

Referenced by do_split_line().

Here is the caller graph for this function:

◆ is_src()

bool Slic3r::Algorithm::is_src ( const ClipperZUtils::ZPoint & p)
static
42{ return p.z() >= 0 && p.z() != CLIP_IDX; }

References CLIP_IDX.

Referenced by do_split_line(), and to_src_idx().

Here is the caller graph for this function:

◆ lower_by_boundary_and_src()

bool Slic3r::Algorithm::lower_by_boundary_and_src ( const WaveSeed & l,
const WaveSeed & r )
inline
48{
49 return l.boundary < r.boundary || (l.boundary == r.boundary && l.src < r.src);
50}
uint32_t boundary
Definition RegionExpansion.hpp:42
uint32_t src
Definition RegionExpansion.hpp:41

References Slic3r::Algorithm::WaveSeed::boundary, and Slic3r::Algorithm::WaveSeed::src.

Referenced by wave_seeds().

Here is the caller graph for this function:

◆ lower_by_src_and_boundary()

bool Slic3r::Algorithm::lower_by_src_and_boundary ( const WaveSeed & l,
const WaveSeed & r )
inline
53{
54 return l.src < r.src || (l.src == r.src && l.boundary < r.boundary);
55}

References Slic3r::Algorithm::WaveSeed::boundary, and Slic3r::Algorithm::WaveSeed::src.

Referenced by Slic3r::expand_bridges_detect_orientations().

Here is the caller graph for this function:

◆ merge_expansions_into_expolygons()

std::vector< ExPolygon > Slic3r::Algorithm::merge_expansions_into_expolygons ( ExPolygons && src,
std::vector< RegionExpansion > && expanded )
515{
516 // expanded regions will be merged into source regions, thus they will be re-sorted by source id.
517 std::sort(expanded.begin(), expanded.end(), [](const auto &l, const auto &r) { return l.src_id < r.src_id; });
518 uint32_t last = 0;
519 Polygons acc;
520 ExPolygons out;
521 out.reserve(src.size());
522 for (auto it = expanded.begin(); it != expanded.end();) {
523 for (; last < it->src_id; ++ last)
524 out.emplace_back(std::move(src[last]));
525 acc.clear();
526 assert(it->src_id == last);
527 for (; it != expanded.end() && it->src_id == last; ++ it)
528 acc.emplace_back(std::move(it->polygon));
529 //FIXME offset & merging could be more efficient, for example one does not need to copy the source expolygon
530 ExPolygon &src_ex = src[last ++];
531 assert(! src_ex.contour.empty());
532#if 0
533 {
534 static int iRun = 0;
535 BoundingBox bbox = get_extents(acc);
536 bbox.merge(get_extents(src_ex));
537 SVG svg(debug_out_path("expand_merge_expolygons-failed-union=%d.svg", iRun ++).c_str(), bbox);
538 svg.draw(acc);
539 svg.draw_outline(acc, "black", scale_(0.05));
540 svg.draw(src_ex, "red");
541 svg.Close();
542 }
543#endif
544 Point sample = src_ex.contour.front();
545 append(acc, to_polygons(std::move(src_ex)));
547 // Expanding one expolygon by waves should not change connectivity of the source expolygon:
548 // Single expolygon should be produced possibly with increased number of holes.
549 if (merged.size() > 1) {
550 // assert(merged.size() == 1);
551 // There is something wrong with the initial waves. Most likely the bridge was not valid at all
552 // or the boundary region was very close to some bridge edge, but not really touching.
553 // Pick only a single merged expolygon, which contains one sample point of the source expolygon.
554 auto aabb_tree = build_aabb_tree_over_expolygons(merged);
555 int id = sample_in_expolygons(aabb_tree, merged, sample);
556 assert(id != -1);
557 if (id != -1)
558 out.emplace_back(std::move(merged[id]));
559 } else if (merged.size() == 1)
560 out.emplace_back(std::move(merged.front()));
561 }
562 for (; last < uint32_t(src.size()); ++ last)
563 out.emplace_back(std::move(src[last]));
564 return out;
565}
Polygon contour
Definition ExPolygon.hpp:42
bool empty() const
Definition MultiPoint.hpp:51
const Point & front() const
Definition MultiPoint.hpp:45
Definition Point.hpp:199
static AABBTreeBBoxes build_aabb_tree_over_expolygons(const ExPolygons &expolygons)
Definition RegionExpansion.cpp:168
static int sample_in_expolygons(const AABBTreeBBoxes &aabb_tree, const ExPolygons &expolygons, const Point &sample)
Definition RegionExpansion.cpp:181
std::vector< ExPolygon > ExPolygons
Definition ExPolygon.hpp:20
Polygons to_polygons(const ExPolygon &src)
Definition ExPolygon.hpp:307
Slic3r::ExPolygons union_safety_offset_ex(const Slic3r::Polygons &polygons)
Definition ClipperUtils.hpp:388
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:157

References Slic3r::append(), build_aabb_tree_over_expolygons(), Slic3r::SVG::Close(), Slic3r::ExPolygon::contour, Slic3r::debug_out_path(), Slic3r::SVG::draw(), Slic3r::SVG::draw_outline(), Slic3r::MultiPoint::empty(), Slic3r::MultiPoint::front(), Slic3r::get_extents(), Slic3r::BoundingBoxBase< PointType, APointsType >::merge(), sample_in_expolygons(), scale_, Slic3r::to_polygons(), and Slic3r::union_safety_offset_ex().

Referenced by expand_merge_expolygons(), and Slic3r::expand_merge_surfaces().

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

◆ merge_splits()

void Slic3r::Algorithm::merge_splits ( ClipperZUtils::ZPaths & paths,
std::vector< std::pair< ClipperZUtils::ZPoint, int > > & splits )
inlinestatic
117{
118 for (auto it_path = paths.begin(); it_path != paths.end(); ) {
119 ClipperZUtils::ZPath &path = *it_path;
120 assert(path.size() >= 2);
121 bool merged = false;
122 if (path.size() >= 2) {
123 const ClipperZUtils::ZPoint &front = path.front();
124 const ClipperZUtils::ZPoint &back = path.back();
125 // The path before clipping was supposed to cross the clipping boundary or be fully out of it.
126 // Thus the clipped contour is supposed to become open, with one exception: The anchor expands into a closed hole.
127 if (front.x() != back.x() || front.y() != back.y()) {
128 // Look up the ends in "splits", possibly join the contours.
129 // "splits" maps into the other piece connected to the same end point.
130 auto find_end = [&splits](const ClipperZUtils::ZPoint &pt) -> std::pair<ClipperZUtils::ZPoint, int>* {
131 auto it = std::lower_bound(splits.begin(), splits.end(), pt,
132 [](const auto &l, const auto &r){ return ClipperZUtils::zpoint_lower(l.first, r); });
133 return it != splits.end() && it->first == pt ? &(*it) : nullptr;
134 };
135 auto *end = find_end(front);
136 bool end_front = true;
137 if (! end) {
138 end_front = false;
139 end = find_end(back);
140 }
141 if (end) {
142 // This segment ends at a split point of the source closed contour before clipping.
143 if (end->second == -1) {
144 // Open end was found, not matched yet.
145 end->second = int(it_path - paths.begin());
146 } else {
147 // Open end was found and matched with end->second
148 ClipperZUtils::ZPath &other_path = paths[end->second];
149 polylines_merge(other_path, other_path.front() == end->first, std::move(path), end_front);
150 if (std::next(it_path) == paths.end()) {
151 paths.pop_back();
152 break;
153 }
154 path = std::move(paths.back());
155 paths.pop_back();
156 merged = true;
157 }
158 }
159 }
160 }
161 if (! merged)
162 ++ it_path;
163 }
164}
T * end(Slic3r::Mat< N, M, T > &mat)
Definition Point.hpp:841
void polylines_merge(PointsType &dst, bool dst_first, PointsType &&src, bool src_first)
Definition Polyline.hpp:241

References Slic3r::polylines_merge().

Referenced by wave_seeds().

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

◆ point_on_line()

bool Slic3r::Algorithm::point_on_line ( const Point & p,
const Line & l )
static
61{
62 // Check collinear
63 const Vec2crd d1 = l.b - l.a;
64 const Vec2crd d2 = p - l.a;
65 if (d1.x() * d2.y() != d1.y() * d2.x()) {
66 return false;
67 }
68
69 // Make sure p is in between line.a and line.b
70 if (l.a.x() != l.b.x())
71 return (p.x() > l.a.x()) == (p.x() < l.b.x());
72 else
73 return (p.y() > l.a.y()) == (p.y() < l.b.y());
74}
Point b
Definition Line.hpp:199
Point a
Definition Line.hpp:198
Eigen::Matrix< coord_t, 2, 1, Eigen::DontAlign > Vec2crd
Definition Point.hpp:52

References Slic3r::Line::a, and Slic3r::Line::b.

Referenced by do_split_line().

Here is the caller graph for this function:

◆ propagate_wave_from_boundary()

Polygons Slic3r::Algorithm::propagate_wave_from_boundary ( const VecOfPoints & seed,
const ExPolygon & boundary,
const float initial_step,
const float other_step,
const size_t num_other_steps,
const float max_inflation,
const double arc_tolerance )
static
410{
411 assert(! seed.empty() && seed.front().size() >= 2);
412 Polygons clipping = ClipperUtils::clip_clipper_polygons_with_subject_bbox(boundary, get_extents<true>(seed).inflated(max_inflation));
413 Polygons polygons = wavefront_clip(wavefront_initial(seed, initial_step, arc_tolerance), clipping);
414 // Now offset the remaining
415 for (size_t ioffset = 0; ioffset < num_other_steps; ++ ioffset)
416 polygons = wavefront_clip(wavefront_step(polygons, other_step, arc_tolerance), clipping);
417 return polygons;
418}
static Polygons wavefront_step(const Polygons &polygons, float offset, double arc_tolerance)
Definition RegionExpansion.cpp:379
static Polygons wavefront_clip(const Polygons &wavefront, const Polygons &clipping)
Definition RegionExpansion.cpp:389
static Polygons wavefront_initial(const VecOfPoints &polylines, float offset, double arc_tolerance)
Definition RegionExpansion.cpp:365
Polygons clip_clipper_polygons_with_subject_bbox(const Polygons &src, const BoundingBox &bbox)
Definition ClipperUtils.cpp:132

References Slic3r::ClipperUtils::clip_clipper_polygons_with_subject_bbox(), Slic3r::get_extents(), wavefront_clip(), wavefront_initial(), and wavefront_step().

Referenced by propagate_waves().

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

◆ propagate_waves() [1/3]

std::vector< RegionExpansion > Slic3r::Algorithm::propagate_waves ( const ExPolygons & src,
const ExPolygons & boundary,
const RegionExpansionParameters & params )
442{
443 return propagate_waves(wave_seeds(src, boundary, params.tiny_expansion, true), boundary, params);
444}
std::vector< WaveSeed > wave_seeds(const ExPolygons &src, const ExPolygons &boundary, float tiny_expansion, bool sorted)
Definition RegionExpansion.cpp:206
float tiny_expansion
Definition RegionExpansion.hpp:17

References propagate_waves(), Slic3r::Algorithm::RegionExpansionParameters::tiny_expansion, and wave_seeds().

Here is the call graph for this function:

◆ propagate_waves() [2/3]

std::vector< RegionExpansion > Slic3r::Algorithm::propagate_waves ( const ExPolygons & src,
const ExPolygons & boundary,
float expansion,
float expansion_step,
size_t max_nr_steps )
453{
454 return propagate_waves(src, boundary, RegionExpansionParameters::build(expansion, expansion_step, max_nr_steps));
455}
static RegionExpansionParameters build(float full_expansion, float expansion_step, size_t max_nr_expansion_steps)
Definition RegionExpansion.cpp:42

References Slic3r::Algorithm::RegionExpansionParameters::build(), and propagate_waves().

Here is the call graph for this function:

◆ propagate_waves() [3/3]

std::vector< RegionExpansion > Slic3r::Algorithm::propagate_waves ( const WaveSeeds & seeds,
const ExPolygons & boundary,
const RegionExpansionParameters & params )
422{
423 std::vector<RegionExpansion> out;
424 VecOfPoints paths;
425 for (auto it_seed = seeds.begin(); it_seed != seeds.end();) {
426 auto it = it_seed;
427 paths.clear();
428 for (; it != seeds.end() && it->boundary == it_seed->boundary && it->src == it_seed->src; ++ it)
429 paths.emplace_back(it->path);
430 // Propagate the wavefront while clipping it with the trimmed boundary.
431 // Collect the expanded polygons, merge them with the source polygons.
433 for (Polygon &polygon : propagate_wave_from_boundary(paths, boundary[it_seed->boundary], params.initial_step, params.other_step, params.num_other_steps, params.max_inflation, params.arc_tolerance))
434 out.push_back({ std::move(polygon), it_seed->src, it_seed->boundary });
435 it_seed = it;
436 }
437
438 return out;
439}
static Polygons propagate_wave_from_boundary(const VecOfPoints &seed, const ExPolygon &boundary, const float initial_step, const float other_step, const size_t num_other_steps, const float max_inflation, const double arc_tolerance)
Definition RegionExpansion.cpp:394
std::vector< Points, PointsAllocator< Points > > VecOfPoints
Definition Point.hpp:81
float initial_step
Definition RegionExpansion.hpp:19
float max_inflation
Definition RegionExpansion.hpp:26
double arc_tolerance
Definition RegionExpansion.hpp:29
size_t num_other_steps
Definition RegionExpansion.hpp:23
float other_step
Definition RegionExpansion.hpp:21

References Slic3r::Algorithm::RegionExpansionParameters::arc_tolerance, Slic3r::Algorithm::RegionExpansionParameters::initial_step, Slic3r::Algorithm::RegionExpansionParameters::max_inflation, Slic3r::Algorithm::RegionExpansionParameters::num_other_steps, Slic3r::Algorithm::RegionExpansionParameters::other_step, and propagate_wave_from_boundary().

Referenced by expand_expolygons(), expand_merge_expolygons(), Slic3r::expand_merge_surfaces(), propagate_waves(), propagate_waves(), and propagate_waves_ex().

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

◆ propagate_waves_ex() [1/2]

std::vector< RegionExpansionEx > Slic3r::Algorithm::propagate_waves_ex ( const ExPolygons & src,
const ExPolygons & boundary,
float full_expansion,
float expansion_step,
size_t max_nr_expansion_steps )
495{
496 auto params = RegionExpansionParameters::build(full_expansion, expansion_step, max_nr_expansion_steps);
497 return propagate_waves_ex(wave_seeds(src, boundary, params.tiny_expansion, true), boundary, params);
498}
std::vector< RegionExpansionEx > propagate_waves_ex(const WaveSeeds &seeds, const ExPolygons &boundary, const RegionExpansionParameters &params)
Definition RegionExpansion.cpp:458

References Slic3r::Algorithm::RegionExpansionParameters::build(), propagate_waves_ex(), and wave_seeds().

Here is the call graph for this function:

◆ propagate_waves_ex() [2/2]

std::vector< RegionExpansionEx > Slic3r::Algorithm::propagate_waves_ex ( const WaveSeeds & seeds,
const ExPolygons & boundary,
const RegionExpansionParameters & params )
459{
460 std::vector<RegionExpansion> expanded = propagate_waves(seeds, boundary, params);
461 assert(std::is_sorted(seeds.begin(), seeds.end(), [](const auto &l, const auto &r){ return l.boundary < r.boundary || (l.boundary == r.boundary && l.src < r.src); }));
462 Polygons acc;
463 std::vector<RegionExpansionEx> out;
464 for (auto it = expanded.begin(); it != expanded.end(); ) {
465 auto it2 = it;
466 acc.clear();
467 for (; it2 != expanded.end() && it2->boundary_id == it->boundary_id && it2->src_id == it->src_id; ++ it2)
468 acc.emplace_back(std::move(it2->polygon));
469 size_t size = it2 - it;
470 if (size == 1)
471 out.push_back({ ExPolygon{std::move(acc.front())}, it->src_id, it->boundary_id });
472 else {
473 ExPolygons expolys = union_ex(acc);
474 reserve_more_power_of_2(out, expolys.size());
475 for (ExPolygon &ex : expolys)
476 out.push_back({ std::move(ex), it->src_id, it->boundary_id });
477 }
478 it = it2;
479 }
480 return out;
481}
void reserve_more_power_of_2(VectorType &vector, size_t n)
Definition Utils.hpp:439
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, PolyFillType fill_type)
Definition ClipperUtils.cpp:1011

References propagate_waves(), Slic3r::reserve_more_power_of_2(), and Slic3r::union_ex().

Referenced by propagate_waves_ex().

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

◆ sample_in_expolygons()

int Slic3r::Algorithm::sample_in_expolygons ( const AABBTreeBBoxes & aabb_tree,
const ExPolygons & expolygons,
const Point & sample )
static
186{
187 int out = -1;
189 [&sample](const AABBTreeBBoxes::Node &node) {
190 return node.bbox.contains(sample);
191 },
192 [&expolygons, &sample, &out](const AABBTreeBBoxes::Node &node) {
193 assert(node.is_leaf());
194 assert(node.is_valid());
195 if (expolygons[node.idx].contains(sample)) {
196 out = int(node.idx);
197 // Stop traversal.
198 return false;
199 }
200 // Continue traversal.
201 return true;
202 });
203 return out;
204}
void traverse(const Tree< Dims, T > &tree, Predicate &&pred, Fn &&callback)
Definition AABBTreeIndirect.hpp:986

References Slic3r::AABBTreeIndirect::traverse().

Referenced by merge_expansions_into_expolygons(), and wave_seeds().

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

◆ split_line()

template<class PathType>
SplittedLine Slic3r::Algorithm::split_line ( const PathType & path,
const ExPolygons & clip,
bool closed )
51{
52 if (path.empty()) {
53 return {};
54 }
55
56 // Convert the input path into an open ZPath
58 p.reserve(path.size() + (closed ? 1 : 0));
59 coord_t z = 0;
60 for (const auto& point : path) {
61 p.emplace_back(point.x(), point.y(), z);
62 z++;
63 }
64 if (closed) {
65 // duplicate the first point at the end to make a closed path open
66 p.emplace_back(p.front());
67 p.back().z() = z;
68 }
69
70 return do_split_line(p, clip, closed);
71}
SplittedLine do_split_line(const ClipperZUtils::ZPath &path, const ExPolygons &clip, bool closed)
Definition LineSplit.cpp:76

References do_split_line().

Referenced by Slic3r::Feature::FuzzySkin::apply_fuzzy_skin(), and Slic3r::Feature::FuzzySkin::apply_fuzzy_skin().

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

◆ to_point()

Point Slic3r::Algorithm::to_point ( const ClipperZUtils::ZPoint & p)
static
55{ return {p.x(), p.y()}; }

Referenced by do_split_line().

Here is the caller graph for this function:

◆ to_src_idx()

size_t Slic3r::Algorithm::to_src_idx ( const ClipperZUtils::ZPoint & p)
static
46{
47 assert(!is_clip(p));
48 if (is_src(p)) {
49 return p.z();
50 } else {
51 return -p.z() - 1;
52 }
53}

References is_clip(), and is_src().

Referenced by do_split_line().

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

◆ wave_seeds()

WaveSeeds Slic3r::Algorithm::wave_seeds ( const ExPolygons & src,
const ExPolygons & boundary,
float tiny_expansion,
bool sorted )
215{
216 assert(tiny_expansion > 0);
217
218 if (src.empty() || boundary.empty())
219 return {};
220
223
224 ClipperZUtils::ZPaths segments;
225 Intersections intersections;
226
227 coord_t idx_boundary_begin = 1;
228 coord_t idx_boundary_end = idx_boundary_begin;
229 coord_t idx_src_end;
230
231 {
232 ClipperZUtils::ClipperZIntersectionVisitor visitor(intersections);
233 // as closed contours
234 ClipperZUtils::ZPaths zboundary = ClipperZUtils::expolygons_to_zpaths(boundary, idx_boundary_end);
235 // as open contours
236 std::vector<std::pair<ClipperZUtils::ZPoint, int>> zsrc_splits;
237 idx_src_end = idx_boundary_end;
238 ClipperZUtils::ZPaths zsrc = expolygons_to_zpaths_expanded_opened(src, tiny_expansion, idx_src_end);
239 zsrc_splits.reserve(zsrc.size());
240 for (const ClipperZUtils::ZPath &path : zsrc) {
241 assert(path.size() >= 2);
242 assert(path.front() == path.back());
243 zsrc_splits.emplace_back(path.front(), -1);
244 }
245 std::sort(zsrc_splits.begin(), zsrc_splits.end(), [](const auto &l, const auto &r){ return ClipperZUtils::zpoint_lower(l.first, r.first); });
246 segments = ClipperZUtils::clip_zpaths(ctIntersection, zsrc, true, zboundary, visitor.clipper_callback());
247 merge_splits(segments, zsrc_splits);
248 }
249
250 // AABBTree over bounding boxes of boundaries.
251 // Only built if necessary, that is if any of the seed contours is closed, thus there is no intersection point
252 // with the boundary and all Z coordinates of the closed contour point to the source contour.
253 AABBTreeBBoxes aabb_tree;
254
255 // Sort paths into their respective islands.
256 // Each src x boundary will be processed (wave expanded) independently.
257 // Multiple pieces of a single src may intersect the same boundary.
258 WaveSeeds out;
259 out.reserve(segments.size());
260 int iseed = 0;
261 for (const ClipperZUtils::ZPath &path : segments) {
262 assert(path.size() >= 2);
263 ClipperZUtils::ZPoint front = path.front();
264 ClipperZUtils::ZPoint back = path.back();
265 // Both ends of a seed segment are supposed to be inside a single boundary expolygon.
266 // Thus as long as the seed contour is not closed, it should be open at a boundary point.
267 assert((front == back && front.z() >= idx_boundary_end && front.z() < idx_src_end) ||
268 //(front.z() < 0 && back.z() < 0));
269 // Hope that at least one end of an open polyline is clipped by the boundary, thus an intersection point is created.
270 (front.z() < 0 || back.z() < 0));
271 // However, with complex geometry, both endpoints may coincide with existing polygon
272 // vertices (z >= 0), which is handled below.
273
274 if (front != back && front.z() >= 0 && back.z() >= 0) {
275 // Very rare case when both endpoints intersect boundary ExPolygons in existing points.
276 // So the ZFillFunction callback hasn't been called.
277 // Both endpoints coincide with existing polygon vertices, so the
278 // ZFillFunction callback was never called. With complex geometry
279 // this is common because source and boundary contours share many
280 // vertices. Determine src_id / boundary_id from Z coordinates
281 // (and fall back to an AABB-tree point-in-polygon test when a
282 // boundary ID is not directly available).
283 coord_t src_z = -1, boundary_z = -1;
284 // Scan all path points for the information we need.
285 for (const ClipperZUtils::ZPoint &point : path) {
286 if (point.z() >= idx_boundary_end && point.z() < idx_src_end && src_z < 0)
287 src_z = point.z();
288 else if (point.z() >= idx_boundary_begin && point.z() < idx_boundary_end && boundary_z < 0)
289 boundary_z = point.z();
290 if (src_z >= 0 && boundary_z >= 0)
291 break;
292 }
293 if (src_z >= 0) {
294 uint32_t src_id = uint32_t(src_z - idx_boundary_end);
295 if (boundary_z >= 0) {
296 out.push_back({ src_id, uint32_t(boundary_z - 1), ClipperZUtils::from_zpath(path) });
297 } else {
298 // Source ID known but boundary unknown – use AABB tree.
299 if (aabb_tree.empty())
300 aabb_tree = build_aabb_tree_over_expolygons(boundary);
301 int boundary_id = sample_in_expolygons(aabb_tree, boundary, Point(front.x(), front.y()));
302 if (boundary_id >= 0)
303 out.push_back({ src_id, uint32_t(boundary_id), ClipperZUtils::from_zpath(path) });
304 }
305 ++ iseed;
306 continue;
307 }
308 // Unable to determine source ID – drop the segment.
309 continue;
310 } else
311 if (front == back && (front.z() < idx_boundary_end)) {
312 // This should be a very rare exception.
313 // See https://github.com/prusa3d/PrusaSlicer/issues/12469.
314 // Segement is open, yet its first point seems to be part of boundary polygon.
315 // Take the first point with src polygon index.
316 for (const ClipperZUtils::ZPoint &point : path) {
317 if (point.z() >= idx_boundary_end) {
318 front = point;
319 back = point;
320 }
321 }
322 }
323
324 const Intersection *intersection = nullptr;
325 auto intersection_point_valid = [idx_boundary_end, idx_src_end](const Intersection &is) {
326 return is.first >= 1 && is.first < idx_boundary_end &&
327 is.second >= idx_boundary_end && is.second < idx_src_end;
328 };
329 if (front.z() < 0) {
330 const Intersection &is = intersections[- front.z() - 1];
331 assert(intersection_point_valid(is));
332 if (intersection_point_valid(is))
333 intersection = &is;
334 }
335 if (! intersection && back.z() < 0) {
336 const Intersection &is = intersections[- back.z() - 1];
337 assert(intersection_point_valid(is));
338 if (intersection_point_valid(is))
339 intersection = &is;
340 }
341 if (intersection) {
342 // The path intersects the boundary contour at least at one side.
343 out.push_back({ uint32_t(intersection->second - idx_boundary_end), uint32_t(intersection->first - 1), ClipperZUtils::from_zpath(path) });
344 } else {
345 // This should be a closed contour.
346 assert(front == back && front.z() >= idx_boundary_end && front.z() < idx_src_end);
347 // Find a source boundary expolygon of one sample of this closed path.
348 if (aabb_tree.empty())
349 aabb_tree = build_aabb_tree_over_expolygons(boundary);
350 int boundary_id = sample_in_expolygons(aabb_tree, boundary, Point(front.x(), front.y()));
351 // Boundary that contains the sample point was found.
352 assert(boundary_id >= 0);
353 if (boundary_id >= 0)
354 out.push_back({ uint32_t(front.z() - idx_boundary_end), uint32_t(boundary_id), ClipperZUtils::from_zpath(path) });
355 }
356 ++ iseed;
357 }
358
359 if (sorted)
360 // Sort the seeds by their intersection boundary and source contour.
361 std::sort(out.begin(), out.end(), lower_by_boundary_and_src);
362 return out;
363}
std::pair< coord_t, coord_t > Intersection
Definition ClipperZUtils.hpp:122
std::vector< Intersection > Intersections
Definition ClipperZUtils.hpp:123
static void merge_splits(ClipperZUtils::ZPaths &paths, std::vector< std::pair< ClipperZUtils::ZPoint, int > > &splits)
Definition RegionExpansion.cpp:116
static ClipperZUtils::ZPaths expolygons_to_zpaths_expanded_opened(const ExPolygons &src, const float expansion, coord_t &base_idx)
Definition RegionExpansion.cpp:92
bool lower_by_boundary_and_src(const WaveSeed &l, const WaveSeed &r)
Definition RegionExpansion.hpp:47
std::vector< WaveSeed > WaveSeeds
Definition RegionExpansion.hpp:45
ZPaths expolygons_to_zpaths(const ExPolygons &src, coord_t &base_idx)
Definition ClipperZUtils.hpp:67
@ Intersection
Definition CSGMesh.hpp:24
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:769
Definition AvoidCrossingPerimeters.cpp:50

References build_aabb_tree_over_expolygons(), Slic3r::ClipperZUtils::clip_zpaths(), Slic3r::ClipperZUtils::ClipperZIntersectionVisitor::clipper_callback(), Slic3r::ctIntersection, Slic3r::AABBTreeIndirect::Tree< ANumDimensions, ACoordType >::empty(), Slic3r::ClipperZUtils::expolygons_to_zpaths(), expolygons_to_zpaths_expanded_opened(), Slic3r::ClipperZUtils::from_zpath(), Slic3r::intersection(), lower_by_boundary_and_src(), merge_splits(), and sample_in_expolygons().

Referenced by propagate_waves(), and propagate_waves_ex().

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

◆ wavefront_clip()

Polygons Slic3r::Algorithm::wavefront_clip ( const Polygons & wavefront,
const Polygons & clipping )
static
390{
391 return intersection(wavefront, clipping, pftPositive);
392}
@ pftPositive
Definition ClipperUtils.hpp:23

References Slic3r::intersection(), and Slic3r::pftPositive.

Referenced by propagate_wave_from_boundary().

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

◆ wavefront_initial()

Polygons Slic3r::Algorithm::wavefront_initial ( const VecOfPoints & polylines,
float offset,
double arc_tolerance )
static
366{
367 Polygons out;
368 out.reserve(polylines.size());
369 for (const Points &path : polylines) {
370 assert(path.size() >= 2);
371 append(out, Slic3r::offset(Polyline(path), offset, jtRound, arc_tolerance, path.front() == path.back() ? etClosedLine : etOpenRound));
372 }
373 return out;
374}
@ jtRound
Definition ClipperUtils.hpp:21
@ etOpenRound
Definition ClipperUtils.hpp:22
@ etClosedLine
Definition ClipperUtils.hpp:22
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73

References Slic3r::append(), Slic3r::etClosedLine, Slic3r::etOpenRound, Slic3r::jtRound, and Slic3r::offset().

Referenced by propagate_wave_from_boundary().

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

◆ wavefront_step()

Polygons Slic3r::Algorithm::wavefront_step ( const Polygons & polygons,
float offset,
double arc_tolerance )
static
380{
381 Polygons out;
382 out.reserve(polygons.size());
383 for (const Polygon &polygon : polygons)
384 // CCW contours grow, CW holes shrink.
385 append(out, Slic3r::offset(polygon, offset, jtRound, arc_tolerance));
386 return out;
387}

References Slic3r::append(), Slic3r::jtRound, and Slic3r::offset().

Referenced by propagate_wave_from_boundary().

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

Variable Documentation

◆ CLIP_IDX

auto Slic3r::Algorithm::CLIP_IDX = std::numeric_limits<coord_t>::max()
staticconstexpr

Referenced by do_split_line(), is_clip(), and is_src().