53 {
54 if (lines.empty())
55 return;
56
57 SparsePointGrid<PathsPointIndex<Paths>, PathsPointIndexLocator<Paths>>
grid(max_stitch_distance, lines.size() * 2);
58
59
60 for (size_t line_idx = 0; line_idx < lines.size(); line_idx++)
61 {
62 const auto line = lines[line_idx];
63 grid.insert(PathsPointIndex<Paths>(&lines, line_idx, 0));
64 grid.insert(PathsPointIndex<Paths>(&lines, line_idx, line.size() - 1));
65 }
66
67 std::vector<bool> processed(lines.size(), false);
68
69 for (size_t line_idx = 0; line_idx < lines.size(); line_idx++)
70 {
71 if (processed[line_idx])
72 {
73 continue;
74 }
75 processed[line_idx] = true;
76 const auto line = lines[line_idx];
77 bool should_close =
isOdd(line);
78
80 bool closest_is_closing_polygon = false;
81 for (bool go_in_reverse_direction : { false, true })
82 {
83 if (go_in_reverse_direction)
84 {
85 chain.reverse();
86 }
87 int64_t chain_length = chain.polylineLength();
88
89 while (true)
90 {
92
93 PathsPointIndex<Paths> closest;
94 coord_t closest_distance = std::numeric_limits<coord_t>::max();
95 grid.processNearby(from, max_stitch_distance,
96 std::function<bool (const PathsPointIndex<Paths>&)> (
97 [from, &chain, &closest, &closest_is_closing_polygon, &closest_distance, &processed, &chain_length, go_in_reverse_direction, max_stitch_distance, snap_distance, should_close]
98 (const PathsPointIndex<Paths>& nearby)->bool
99 {
100 bool is_closing_segment = false;
101 coord_t dist = (nearby.p().
template cast<int64_t>() - from.template cast<int64_t>()).norm();
102 if (dist > max_stitch_distance)
103 {
104 return true;
105 }
106 if ((nearby.p().template cast<int64_t>() -
make_point(chain.front()).template cast<int64_t>()).squaredNorm() < snap_distance * snap_distance)
107 {
108 if (chain_length + dist < 3 * max_stitch_distance
109 || chain.size() <= 2)
110 {
111 return true;
112 }
113 is_closing_segment = true;
114 if (!should_close)
115 {
116 dist += scaled<coord_t>(0.01);
117
118
119 }
120 else
121 {
122 dist -= scaled<coord_t>(0.01);
123
124 }
125 }
126 else if (processed[nearby.poly_idx])
127 {
128 return true;
129 }
130 bool nearby_would_be_reversed = nearby.point_idx != 0;
131 nearby_would_be_reversed = nearby_would_be_reversed != go_in_reverse_direction;
132 if (!
canReverse(nearby) && nearby_would_be_reversed)
133 {
134 return true;
135 }
136 if (!
canConnect(chain, (*nearby.polygons)[nearby.poly_idx]))
137 {
138 return true;
139 }
140 if (dist < closest_distance)
141 {
142 closest_distance =
dist;
143 closest = nearby;
144 closest_is_closing_polygon = is_closing_segment;
145 }
146 if (dist < snap_distance)
147 {
148 return false;
149 }
150 return true;
151 })
152 );
153
154 if (!closest.initialized()
155 || closest_is_closing_polygon
156 )
157 {
158 break;
159 }
160
161 coord_t segment_dist = (
make_point(chain.back()).template cast<int64_t>() - closest.p().template cast<int64_t>()).norm();
162 assert(segment_dist <= max_stitch_distance + scaled<coord_t>(0.01));
163 const size_t old_size = chain.size();
164 if (closest.point_idx == 0)
165 {
166 auto start_pos = (*closest.polygons)[closest.poly_idx].begin();
167 if (segment_dist < snap_distance)
168 {
169 ++start_pos;
170 }
171 chain.insert(chain.end(), start_pos, (*closest.polygons)[closest.poly_idx].end());
172 }
173 else
174 {
175 auto start_pos = (*closest.polygons)[closest.poly_idx].rbegin();
176 if (segment_dist < snap_distance)
177 {
178 ++start_pos;
179 }
180 chain.insert(chain.end(), start_pos, (*closest.polygons)[closest.poly_idx].rend());
181 }
182 for(size_t i = old_size; i < chain.size(); ++i)
183 {
184 chain_length += (
make_point(chain[i]).template cast<int64_t>() -
make_point(chain[i - 1]).template cast<int64_t>()).norm();
185 }
186 should_close = should_close & !
isOdd((*closest.polygons)[closest.poly_idx]);
187 assert( ! processed[closest.poly_idx]);
188 processed[closest.poly_idx] = true;
189 }
190 if (closest_is_closing_polygon)
191 {
192 if (go_in_reverse_direction)
193 {
194
195 chain.reverse();
196 }
197
198 break;
199 }
200 }
201 if (closest_is_closing_polygon)
202 {
203 result_polygons.emplace_back(chain);
204 }
205 else
206 {
207 PathsPointIndex<Paths> ppi_here(&lines, line_idx, 0);
209 {
210
211 chain.reverse();
212 }
213 result_lines.emplace_back(chain);
214 }
215 }
216 }
static bool canReverse(const PathsPointIndex< Paths > &polyline)
static bool isOdd(const Path &line)
static bool canConnect(const Path &a, const Path &b)
int32_t coord_t
Definition libslic3r.h:39
std::vector< IntPoint, Allocator< IntPoint > > Path
Definition clipper.hpp:121
const Point & make_point(const ExtrusionJunction &ej)
Definition ExtrusionJunction.hpp:51
T dist(const boost::polygon::point_data< T > &p1, const boost::polygon::point_data< T > &p2)
Definition Geometry.cpp:280
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
Kernel::Point_2 Point
Definition point_areas.cpp:20
__int64 int64_t
Definition unistd.h:76