77{
78 assert(path.size() > 1);
79#ifdef DEBUG_SPLIT_LINE
84 const std::uint32_t dbg_id = g_dbg_id++;
85 {
87 svg.draw(clip, "red", 0.5);
88 svg.draw_outline(clip, "red");
90 svg.draw(dbg_path_points);
91 svg.Close();
92 }
93#endif
94
96
97 {
98
100 for (const auto& exp : clip) {
102 for (const Polygon& hole : exp.holes)
104 }
105
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");
120 svg.draw(Polyline{segment_points});
122 const auto z = p.z();
127 } else {
129 }
130 }
131 svg.Close();
132 i++;
133 }
134 }
135#endif
136
137
138 std::vector<SplitNode> split_chain;
139 {
140
141
142
143 AABBTreeLines::LinesDistancer<Line> aabb_tree;
146 return;
147 }
148
149 if (aabb_tree.get_lines().empty()) {
151 lines.reserve(path.size() - 1);
152 for (auto it = path.begin() + 1; it != path.end(); ++it) {
154 }
155 aabb_tree = AABBTreeLines::LinesDistancer(lines);
156 }
157
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
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 }
173 zp.z() = -(path[l].z() + 1);
174 break;
175 }
176 }
178
179 zp.z() = -(path[possible_edges[0]].z() + 1);
180 }
181 };
182
183 split_chain.assign(path.size(), {});
186
187 std::for_each(
segment.begin(),
segment.end(), resolve_clip_point);
188
189
191 if (is_new(a) && is_new(b) && a.z() == b.z()) {
192
193 const auto src = to_point(path[-a.z() - 1]);
194 return (to_point(a) - src).squaredNorm() < (to_point(b) - src).squaredNorm();
195 }
198 if (a_idx == b_idx) {
199
201 } else {
202 return a_idx < b_idx;
203 }
204 });
205
206
210
211
212
213
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;
221 const auto dist2 = (front - src_p).block<2, 1>(0,0).squaredNorm();
222
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
234 node.insert(it, &segment);
235
236 previous_src_point = &src_p;
237 } else {
238 assert(false);
239 }
240
241
245 previous_src_point = &p;
247
248 p.z() = -(previous_src_point->z() + 1);
249 }
250 }
251 }
252 }
253
254
256 size_t idx = 0;
257 while (idx < split_chain.size()) {
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
267
268 result.emplace_back(
to_point(p),
false, idx);
269 }
270 }
271 for (const auto segment : node) {
274 result.emplace_back(
to_point(sp),
true, sp.z());
275 }
276 result.back().clipped = false;
277 }
278
279
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
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
#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