Removes vertices of the ExtrusionLines to make sure that they are not too high resolution.
This removes junctions which are connected to line segments that are shorter than the smallest_line_segment, unless that would introduce a deviation in the contour of more than allowed_error_distance.
Simplify uses a heuristic and doesn't necessarily remove all removable vertices under the above criteria, but simplify may never violate these criteria. Unless the segments or the distance is smaller than the rounding error of 5 micron.
Vertices which introduce an error of less than 5 microns are removed anyway, even if the segments are longer than the smallest line segment. This makes sure that (practically) co-linear line segments are joined into a single line segment.
49{
50 const size_t min_path_size =
is_closed ? 3 : 2;
52 return;
53
54
55
56
57
58 std::vector<ExtrusionJunction> new_junctions;
59
60 new_junctions.emplace_back(
junctions.front());
61
62 ExtrusionJunction previous =
junctions.front();
63
64
65
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 const ExtrusionJunction& initial =
junctions[1];
89 int64_t accumulated_area_removed = int64_t(previous.p.x()) * int64_t(initial.p.y()) - int64_t(previous.p.y()) * int64_t(initial.p.x());
90
91
92 for (
size_t point_idx = 1; point_idx <
junctions.size() - (this->
is_closed ? 0 : 1); point_idx++)
93 {
94
95 const bool is_last = point_idx + 1 ==
junctions.size();
96 const ExtrusionJunction& current = is_last ? new_junctions[0] :
junctions[point_idx];
97
98
100 new_junctions.push_back(current);
101 continue;
102 }
103
104
106 point_idx + 2 -
junctions.size() < new_junctions.size();
107 ExtrusionJunction& next = spill_over ? new_junctions[point_idx + 2 -
junctions.size()] :
junctions[point_idx + 1];
108
109 const int64_t removed_area_next = int64_t(current.p.x()) * int64_t(next.p.y()) - int64_t(current.p.y()) * int64_t(next.p.x());
110 const int64_t negative_area_closing = int64_t(next.p.x()) * int64_t(previous.p.y()) - int64_t(next.p.y()) * int64_t(previous.p.x());
111 accumulated_area_removed += removed_area_next;
112
113 const int64_t length2 = (current - previous).
cast<int64_t>().squaredNorm();
114
115
116
117
119 {
120
121 continue;
122 }
123
124 const int64_t area_removed_so_far = accumulated_area_removed + negative_area_closing;
125 const int64_t base_length_2 = (next - previous).
cast<int64_t>().squaredNorm();
126
127 if (base_length_2 == 0)
128 {
129 continue;
130 }
131
132
133
134
135
136
137
138 const auto height_2 = int64_t(double(area_removed_so_far) * double(area_removed_so_far) / double(base_length_2));
140
143
144 && extrusion_area_error <= maximum_extrusion_area_deviation)
145 {
146
147 continue;
148 }
149
150 if (length2 < smallest_line_segment_squared
151 && height_2 <= allowed_error_distance_squared)
152 {
153 const int64_t next_length2 = (current - next).
cast<int64_t>().squaredNorm();
154 if (next_length2 > 4 * smallest_line_segment_squared)
155 {
156
157
158
159
160
161
162
163
164
165
166 Point intersection_point;
167 bool has_intersection = Line(previous_previous.p, previous.p).intersection_infinite(Line(current.p, next.p), &intersection_point);
168 const auto dist_greater = [](
const Point& p1,
const Point& p2,
const int64_t threshold) {
169 const auto vec = (p1 - p2).cwiseAbs().cast<uint64_t>().eval();
170 if(vec.x() > threshold || vec.y() > threshold) {
171
172
173 return true;
174 }
175 return vec.squaredNorm() > threshold;
176 };
177 if (!has_intersection
179 || dist_greater(intersection_point, previous.p, smallest_line_segment_squared)
180 || dist_greater(intersection_point, current.p, smallest_line_segment_squared))
181 {
182
183
184 }
185 else
186 {
187
188 const ExtrusionJunction new_to_add = ExtrusionJunction(intersection_point, current.w, current.perimeter_index);
189
190 if(!new_junctions.empty())
191 {
192 new_junctions.pop_back();
193 previous = previous_previous;
194 }
195
196
197 accumulated_area_removed = removed_area_next;
198 previous_previous = previous;
199 previous = new_to_add;
200 new_junctions.push_back(new_to_add);
201 continue;
202 }
203 }
204 else
205 {
206 continue;
207 }
208 }
209
210 accumulated_area_removed = removed_area_next;
211 previous_previous = previous;
212 previous = current;
213 new_junctions.push_back(current);
214 }
215
217
218
219
220 new_junctions.front().p = new_junctions.back().p;
221 } else {
222
223 new_junctions.emplace_back(
junctions.back());
224 }
225
227}
double distance_to_infinite_squared(const Point &point, Point *closest_point) const
Definition Line.hpp:173
static double distance_to_infinite(const Point &point, const Point &a, const Point &b)
Definition Line.hpp:196
coord_t colinear_vertex_tolerance()
Definition ExtrusionLine.hpp:40
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
BoundingBox scaled(const BoundingBoxf &bb)
Definition BoundingBox.hpp:284
constexpr T sqr(T x)
Definition libslic3r.h:301
static int64_t calculateExtrusionAreaDeviationError(ExtrusionJunction A, ExtrusionJunction B, ExtrusionJunction C)
Definition ExtrusionLine.cpp:229