Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::Voronoi::detail Namespace Reference

Classes

struct  Intersections
 

Functions

double first_circle_segment_intersection_parameter (const Vec2d &center, const double r, const Vec2d &pt, const Vec2d &v)
 
Intersections point_point_equal_distance_points (const Point &pt1, const Point &pt2, const double d)
 
Intersections line_point_equal_distance_points (const Line &line, const Point &ipt, const double d)
 
template<typename VertexType >
bool vertex_equal_to_point (const VertexType &vertex, const Point &ipt)
 
bool vertex_equal_to_point (const VD::vertex_type *vertex, const Point &ipt)
 
double dist_to_site (const Lines &lines, const VD::cell_type &cell, const Vec2d &point)
 
bool on_site (const Lines &lines, const VD::cell_type &cell, const Vec2d &pt)
 
std::pair< Vec2d, Vec2dpoint_point_dr_dl_thresholds (const Point &pt1_site, const Point &pt2_site, const Vec2d &voronoi_point1, const Vec2d &voronoi_point2, const double threshold_tan_alpha_half)
 
std::pair< Vec2d, Vec2dpoint_segment_dr_dl_thresholds (const Point &pt_site, const Line &line_site, const Vec2d &voronoi_point1, const Vec2d &voronoi_point2, const double threshold_tan_alpha_half)
 
std::pair< Vec2d, Vec2dpoint_point_skeleton_thresholds (const Point &pt1_site, const Point &pt2_site, const Vec2d &voronoi_point1, const Vec2d &voronoi_point2, const double tan_alpha_half)
 
std::pair< Vec2d, Vec2dpoint_segment_skeleton_thresholds (const Point &pt_site, const Line &line_site, const Vec2d &voronoi_point1, const Vec2d &voronoi_point2, const double threshold_cos_alpha)
 

Class Documentation

◆ Slic3r::Voronoi::detail::Intersections

struct Slic3r::Voronoi::detail::Intersections
+ Collaboration diagram for Slic3r::Voronoi::detail::Intersections:
Class Members
int count
Vec2d pts[2]

Function Documentation

◆ dist_to_site()

double Slic3r::Voronoi::detail::dist_to_site ( const Lines lines,
const VD::cell_type &  cell,
const Vec2d point 
)
229 {
230 const Line &line = lines[cell.source_index()];
231 return cell.contains_point() ?
232 (((cell.source_category() == boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT) ? line.a : line.b).cast<double>() - point).norm() :
233 (Geometry::foot_pt<Vec2d>(line.a.cast<double>(), (line.b - line.a).cast<double>(), point) - point).norm();
234 };
EIGEN_DEVICE_FUNC CastXpr< NewType >::Type cast() const
Definition CommonCwiseUnaryOps.h:62
Definition Line.hpp:155
Point a
Definition Line.hpp:197

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

Referenced by Slic3r::Voronoi::edge_offset_contour_intersections(), Slic3r::Voronoi::offset(), Slic3r::Voronoi::debug::verify_offset_intersection_points(), and Slic3r::Voronoi::debug::verify_signed_distances().

+ Here is the caller graph for this function:

◆ first_circle_segment_intersection_parameter()

double Slic3r::Voronoi::detail::first_circle_segment_intersection_parameter ( const Vec2d center,
const double  r,
const Vec2d pt,
const Vec2d v 
)
25 {
26 const Vec2d d = pt - center;
27#ifndef NDEBUG
28 // Start point should be inside, end point should be outside the circle.
29 double d0 = (pt - center).norm();
30 double d1 = (pt + v - center).norm();
31 assert(d0 < r + SCALED_EPSILON);
32 assert(d1 > r - SCALED_EPSILON);
33#endif /* NDEBUG */
34 const double a = v.squaredNorm();
35 const double b = 2. * d.dot(v);
36 const double c = d.squaredNorm() - r * r;
37 std::pair<int, std::array<double, 2>> out;
38 double u = b * b - 4. * a * c;
39 assert(u > - EPSILON);
40 double t;
41 if (u <= 0) {
42 // Degenerate to a single closest point.
43 t = - b / (2. * a);
44 assert(t >= - EPSILON && t <= 1. + EPSILON);
45 return std::clamp(t, 0., 1.);
46 } else {
47 u = sqrt(u);
48 out.first = 2;
49 double t0 = (- b - u) / (2. * a);
50 double t1 = (- b + u) / (2. * a);
51 // One of the intersections shall be found inside the segment.
52 assert((t0 >= - EPSILON && t0 <= 1. + EPSILON) || (t1 >= - EPSILON && t1 <= 1. + EPSILON));
53 if (t1 < 0.)
54 return 0.;
55 if (t0 > 1.)
56 return 1.;
57 return (t0 > 0.) ? t0 : t1;
58 }
59 }
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
Definition ArrayCwiseUnaryOps.h:152
#define SCALED_EPSILON
Definition libslic3r.h:71
static constexpr double EPSILON
Definition libslic3r.h:51

References EPSILON, SCALED_EPSILON, and sqrt().

Referenced by Slic3r::Voronoi::edge_offset_contour_intersections().

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

◆ line_point_equal_distance_points()

Intersections Slic3r::Voronoi::detail::line_point_equal_distance_points ( const Line line,
const Point ipt,
const double  d 
)
120 {
121 assert(line.a != ipt && line.b != ipt);
122 // Calculating two points of distance "d" to a ray and a point.
123 // Point.
124 Vec2d pt = ipt.cast<double>();
125 Vec2d lv = (line.b - line.a).cast<double>();
126 double l2 = lv.squaredNorm();
127 Vec2d lpv = (line.a - ipt).cast<double>();
128 double c = cross2(lpv, lv);
129 if (c < 0) {
130 lv = - lv;
131 c = - c;
132 }
133
134 // Line equation (ax + by + c - d * sqrt(l2)).
135 auto a = - lv.y();
136 auto b = lv.x();
137 // Line point shifted by -ipt is on the line.
138 assert(std::abs(lpv.x() * a + lpv.y() * b + c) < SCALED_EPSILON);
139 // Line vector (a, b) points towards ipt.
140 assert(a * lpv.x() + b * lpv.y() < - SCALED_EPSILON);
141
142#ifndef NDEBUG
143 {
144 // Foot point of ipt on line.
145 Vec2d ft = Geometry::foot_pt(line, ipt);
146 // Center point between ipt and line, its distance to both line and ipt is equal.
147 Vec2d centerpt = 0.5 * (ft + pt) - pt;
148 double dcenter = 0.5 * (ft - pt).norm();
149 // Verify that the center point
150 assert(std::abs(centerpt.x() * a + centerpt.y() * b + c - dcenter * sqrt(l2)) < SCALED_EPSILON * sqrt(l2));
151 }
152#endif // NDEBUG
153
154 // Calculate the two intersection points.
155 // With the help of Python package sympy:
156 // res = solve([a * x + b * y + c - d * sqrt(a**2 + b**2), x**2 + y**2 - d**2], [x, y])
157 // ccode(cse((res[0][0], res[0][1], res[1][0], res[1][1])))
158 // where (a, b, c, d) is the line equation, not normalized (vector a,b is not normalized),
159 // d is distance from the line and the point (0, 0).
160 // The result is then shifted to ipt.
161
162 double dscaled = d * sqrt(l2);
163 double s = c * (2. * dscaled - c);
164 if (s < 0.)
165 // Distance of pt from line is bigger than 2 * d.
166 return Intersections { 0 };
167 double u;
168 int cnt;
169 // Avoid division by zero if a gets too small.
170 bool xy_swapped = std::abs(a) < std::abs(b);
171 if (xy_swapped)
172 std::swap(a, b);
173 if (s == 0.) {
174 // Distance of pt from line is 2 * d.
175 cnt = 1;
176 u = 0.;
177 } else {
178 // Distance of pt from line is smaller than 2 * d.
179 cnt = 2;
180 u = a * sqrt(s) / l2;
181 }
182 double e = dscaled - c;
183 double f = b * e / l2;
184 double g = f - u;
185 double h = f + u;
186 Intersections out { cnt, { Vec2d((- b * g + e) / a, g),
187 Vec2d((- b * h + e) / a, h) } };
188 if (xy_swapped) {
189 std::swap(out.pts[0].x(), out.pts[0].y());
190 std::swap(out.pts[1].x(), out.pts[1].y());
191 }
192 out.pts[0] += pt;
193 out.pts[1] += pt;
194
195 assert(std::abs(Geometry::ray_point_distance<Vec2d>(line.a.cast<double>(), (line.b - line.a).cast<double>(), out.pts[0]) - d) < SCALED_EPSILON);
196 assert(std::abs(Geometry::ray_point_distance<Vec2d>(line.a.cast<double>(), (line.b - line.a).cast<double>(), out.pts[1]) - d) < SCALED_EPSILON);
197 assert(std::abs((out.pts[0] - ipt.cast<double>()).norm() - d) < SCALED_EPSILON);
198 assert(std::abs((out.pts[1] - ipt.cast<double>()).norm() - d) < SCALED_EPSILON);
199 return out;
200 }
Point b
Definition Line.hpp:198
T l2(const boost::geometry::model::d2::point_xy< T > &v)
Definition ExtrusionSimulator.cpp:166
Derived::Scalar cross2(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:93
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:51

References Slic3r::Line::a, Slic3r::Line::b, Slic3r::cross2(), Slic3r::f(), Slic3r::Geometry::foot_pt(), Slic3r::l2(), SCALED_EPSILON, and sqrt().

Referenced by Slic3r::Voronoi::edge_offset_contour_intersections().

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

◆ on_site()

bool Slic3r::Voronoi::detail::on_site ( const Lines lines,
const VD::cell_type &  cell,
const Vec2d pt 
)
237 {
238 const Line &line = lines[cell.source_index()];
239 auto on_contour = [&pt](const Point &ipt) { return detail::vertex_equal_to_point(pt, ipt); };
240 if (cell.contains_point()) {
241 return on_contour(contour_point(cell, line));
242 } else {
243 assert(! (on_contour(line.a) && on_contour(line.b)));
244 return on_contour(line.a) || on_contour(line.b);
245 }
246 };
Definition Point.hpp:158
const Point & contour_point(const VD::cell_type &cell, const Line &line)
Definition VoronoiOffset.hpp:16

References Slic3r::Line::a, Slic3r::Line::b, Slic3r::Voronoi::contour_point(), and vertex_equal_to_point().

Referenced by Slic3r::Voronoi::annotate_inside_outside(), and Slic3r::Voronoi::debug::verify_vertices_on_contour().

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

◆ point_point_dr_dl_thresholds()

std::pair< Vec2d, Vec2d > Slic3r::Voronoi::detail::point_point_dr_dl_thresholds ( const Point pt1_site,
const Point pt2_site,
const Vec2d voronoi_point1,
const Vec2d voronoi_point2,
const double  threshold_tan_alpha_half 
)
264 {
265 // sympy code to calculate +-x
266 // of a linear bisector of pt1_site, pt2_site parametrized with pt + x * v, |v| = 1
267 // where dr/dl = threshold_dr_dl
268 // equals d|pt1_site - pt + x * v| / dx = threshold_dr_dl
269 //
270 // y = sqrt(x^2 + d^2)
271 // dy = diff(y, x)
272 // solve(dy - c, x)
273 //
274 // Project voronoi_point1/2 to line_site.
275 Vec2d dir_y = (pt2_site - pt1_site).cast<double>();
276 Vec2d dir_x = Vec2d(- dir_y.y(), dir_y.x()).normalized();
277 Vec2d cntr = 0.5 * (pt1_site.cast<double>() + pt2_site.cast<double>());
278 double t1 = (voronoi_point1 - cntr).dot(dir_x);
279 double t2 = (voronoi_point2 - cntr).dot(dir_x);
280 if (t1 > t2) {
281 t1 = -t1;
282 t2 = -t2;
283 dir_x = - dir_x;
284 }
285 auto x = 0.5 * dir_y.norm() * threshold_tan_alpha_half;
286 static constexpr double nan = std::numeric_limits<double>::quiet_NaN();
287 auto out = std::make_pair(Vec2d(nan, nan), Vec2d(nan, nan));
288 if (t2 > -x && t1 < x) {
289 // Intervals overlap.
290 dir_x *= x;
291 out.first = (t1 < -x) ? cntr - dir_x : voronoi_point1;
292 out.second = (t2 > +x) ? cntr + dir_x : voronoi_point2;
293 }
294 return out;
295 }

References Slic3r::dot().

Referenced by Slic3r::Voronoi::skeleton_edges_rough().

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

◆ point_point_equal_distance_points()

Intersections Slic3r::Voronoi::detail::point_point_equal_distance_points ( const Point pt1,
const Point pt2,
const double  d 
)
69 {
70 // Calculate the two intersection points.
71 // With the help of Python package sympy:
72 // res = solve([(x - cx)**2 + (y - cy)**2 - d**2, x**2 + y**2 - d**2], [x, y])
73 // ccode(cse((res[0][0], res[0][1], res[1][0], res[1][1])))
74 // where cx, cy is the center of pt1 relative to pt2,
75 // d is distance from the line and the point (0, 0).
76 // The result is then shifted to pt2.
77 auto cx = double(pt1.x() - pt2.x());
78 auto cy = double(pt1.y() - pt2.y());
79 double cl = cx * cx + cy * cy;
80 double discr = 4. * d * d - cl;
81 if (discr < 0.) {
82 // No intersection point found, the two circles are too far away.
83 return Intersections { 0, { Vec2d(), Vec2d() } };
84 }
85 // Avoid division by zero if a gets too small.
86 bool xy_swapped = std::abs(cx) < std::abs(cy);
87 if (xy_swapped)
88 std::swap(cx, cy);
89 double u;
90 int cnt;
91 if (discr == 0.) {
92 cnt = 1;
93 u = 0;
94 } else {
95 cnt = 2;
96 u = 0.5 * cx * sqrt(cl * discr) / cl;
97 }
98 double v = 0.5 * cy - u;
99 double w = 2. * cy;
100 double e = 0.5 / cx;
101 double f = 0.5 * cy + u;
102 Intersections out { cnt, { Vec2d(-e * (v * w - cl), v),
103 Vec2d(-e * (w * f - cl), f) } };
104 if (xy_swapped) {
105 std::swap(out.pts[0].x(), out.pts[0].y());
106 std::swap(out.pts[1].x(), out.pts[1].y());
107 }
108 out.pts[0] += pt2.cast<double>();
109 out.pts[1] += pt2.cast<double>();
110
111 assert(std::abs((out.pts[0] - pt1.cast<double>()).norm() - d) < SCALED_EPSILON);
112 assert(std::abs((out.pts[1] - pt1.cast<double>()).norm() - d) < SCALED_EPSILON);
113 assert(std::abs((out.pts[0] - pt2.cast<double>()).norm() - d) < SCALED_EPSILON);
114 assert(std::abs((out.pts[1] - pt2.cast<double>()).norm() - d) < SCALED_EPSILON);
115 return out;
116 }
Definition VoronoiOffset.cpp:62

References Slic3r::f(), SCALED_EPSILON, and sqrt().

Referenced by Slic3r::Voronoi::edge_offset_contour_intersections().

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

◆ point_point_skeleton_thresholds()

std::pair< Vec2d, Vec2d > Slic3r::Voronoi::detail::point_point_skeleton_thresholds ( const Point pt1_site,
const Point pt2_site,
const Vec2d voronoi_point1,
const Vec2d voronoi_point2,
const double  tan_alpha_half 
)
369 {
370 // Project voronoi_point1/2 to line_site.
371 Vec2d dir_y = (pt2_site - pt1_site).cast<double>();
372 Vec2d dir_x = Vec2d(- dir_y.y(), dir_y.x()).normalized();
373 Vec2d cntr = 0.5 * (pt1_site.cast<double>() + pt2_site.cast<double>());
374 double t1 = (voronoi_point1 - cntr).dot(dir_x);
375 double t2 = (voronoi_point2 - cntr).dot(dir_x);
376 if (t1 > t2) {
377 t1 = -t1;
378 t2 = -t2;
379 dir_x = - dir_x;
380 }
381 auto x = 0.5 * dir_y.norm() * tan_alpha_half;
382 static constexpr double nan = std::numeric_limits<double>::quiet_NaN();
383 auto out = std::make_pair(Vec2d(nan, nan), Vec2d(nan, nan));
384 if (t2 > -x && t1 < x) {
385 // Intervals overlap.
386 dir_x *= x;
387 out.first = (t1 < -x) ? cntr - dir_x : voronoi_point1;
388 out.second = (t2 > +x) ? cntr + dir_x : voronoi_point2;
389 }
390 return out;
391 }

References Slic3r::dot().

+ Here is the call graph for this function:

◆ point_segment_dr_dl_thresholds()

std::pair< Vec2d, Vec2d > Slic3r::Voronoi::detail::point_segment_dr_dl_thresholds ( const Point pt_site,
const Line line_site,
const Vec2d voronoi_point1,
const Vec2d voronoi_point2,
const double  threshold_tan_alpha_half 
)
313 {
314 // sympy code to calculate +-x
315 // of a parabola y = ax^2 + b
316 // where dr/dl = threshold_dr_dl
317 //
318 // a = 1 / (4 * b)
319 // y = a*x**2 + b
320 // dy = diff(y, x)
321 // solve(dy / sqrt(1 + dy**2) - c, x)
322 //
323 // Foot point of the point site on the line site.
324 Vec2d ft = Geometry::foot_pt(line_site, pt_site);
325 // Minimum distance of the bisector (parabolic arc) from the two sites, squared.
326 Vec2d dir_pt_ft = pt_site.cast<double>() - ft;
327 double b = 0.5 * dir_pt_ft.norm();
328 static constexpr double nan = std::numeric_limits<double>::quiet_NaN();
329 auto out = std::make_pair(Vec2d(nan, nan), Vec2d(nan, nan));
330 {
331 // +x, -x are the two parameters along the line_site, where threshold_tan_alpha_half is met.
332 double x = 2. * b * threshold_tan_alpha_half;
333 // Project voronoi_point1/2 to line_site.
334 Vec2d dir_x = (line_site.b - line_site.a).cast<double>().normalized();
335 double t1 = (voronoi_point1 - ft).dot(dir_x);
336 double t2 = (voronoi_point2 - ft).dot(dir_x);
337 if (t1 > t2) {
338 t1 = -t1;
339 t2 = -t2;
340 dir_x = - dir_x;
341 }
342 if (t2 > -x && t1 < x) {
343 // Intervals overlap.
344 bool t1_valid = t1 < -x;
345 bool t2_valid = t2 > +x;
346 // Direction of the Y axis of the parabola.
347 Vec2d dir_y(- dir_x.y(), dir_x.x());
348 // Orient the Y axis towards the point site.
349 if (dir_y.dot(dir_pt_ft) < 0.)
350 dir_y = - dir_y;
351 // Equation of the parabola: y = b + a * x^2
352 double a = 0.25 / b;
353 dir_x *= x;
354 dir_y *= b + a * x * x;
355 out.first = t1_valid ? ft - dir_x + dir_y : voronoi_point1;
356 out.second = t2_valid ? ft + dir_x + dir_y : voronoi_point2;
357 }
358 }
359 return out;
360 }

References Slic3r::Line::a, Slic3r::Line::b, Slic3r::dot(), and Slic3r::Geometry::foot_pt().

Referenced by Slic3r::Voronoi::skeleton_edges_rough().

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

◆ point_segment_skeleton_thresholds()

std::pair< Vec2d, Vec2d > Slic3r::Voronoi::detail::point_segment_skeleton_thresholds ( const Point pt_site,
const Line line_site,
const Vec2d voronoi_point1,
const Vec2d voronoi_point2,
const double  threshold_cos_alpha 
)
400 {
401 // Foot point of the point site on the line site.
402 Vec2d ft = Geometry::foot_pt(line_site, pt_site);
403 // Minimum distance of the bisector (parabolic arc) from the two sites, squared.
404 Vec2d dir_pt_ft = pt_site.cast<double>() - ft;
405 // Distance of Voronoi point site from the Voronoi line site.
406 double l = dir_pt_ft.norm();
407 static constexpr double nan = std::numeric_limits<double>::quiet_NaN();
408 auto out = std::make_pair(Vec2d(nan, nan), Vec2d(nan, nan));
409 // +x, -x are the two parameters along the line_site, where threshold is met.
410 double r = l / (1. + threshold_cos_alpha);
411 double x2 = r * r - Slic3r::sqr(l - r);
412 double x = sqrt(x2);
413 // Project voronoi_point1/2 to line_site.
414 Vec2d dir_x = (line_site.b - line_site.a).cast<double>().normalized();
415 double t1 = (voronoi_point1 - ft).dot(dir_x);
416 double t2 = (voronoi_point2 - ft).dot(dir_x);
417 if (t1 > t2) {
418 t1 = -t1;
419 t2 = -t2;
420 dir_x = - dir_x;
421 }
422 if (t2 > -x && t1 < x) {
423 // Intervals overlap.
424 bool t1_valid = t1 < -x;
425 bool t2_valid = t2 > +x;
426 // Direction of the Y axis of the parabola.
427 Vec2d dir_y(- dir_x.y(), dir_x.x());
428 // Orient the Y axis towards the point site.
429 if (dir_y.dot(dir_pt_ft) < 0.)
430 dir_y = - dir_y;
431 // Equation of the parabola: y = b + a * x^2
432 double a = 0.5 / l;
433 dir_x *= x;
434 dir_y *= 0.5 * l + a * x2;
435 out.first = t1_valid ? ft - dir_x + dir_y : voronoi_point1;
436 out.second = t2_valid ? ft + dir_x + dir_y : voronoi_point2;
437 }
438 return out;
439 }
constexpr T sqr(T x)
Definition libslic3r.h:258

References Slic3r::Line::a, Slic3r::Line::b, Slic3r::dot(), Slic3r::Geometry::foot_pt(), Slic3r::sqr(), and sqrt().

+ Here is the call graph for this function:

◆ vertex_equal_to_point() [1/2]

bool Slic3r::Voronoi::detail::vertex_equal_to_point ( const VD::vertex_type *  vertex,
const Point ipt 
)
226 { return vertex_equal_to_point(*vertex, ipt); }
bool vertex_equal_to_point(const VertexType &vertex, const Point &ipt)
Definition VoronoiOffset.cpp:204

References vertex_equal_to_point().

+ Here is the call graph for this function:

◆ vertex_equal_to_point() [2/2]

template<typename VertexType >
bool Slic3r::Voronoi::detail::vertex_equal_to_point ( const VertexType &  vertex,
const Point ipt 
)
inline
205 {
206 // Convert ipt to doubles, force the 80bit FPU temporary to 64bit and then compare.
207 // This should work with any settings of math compiler switches and the C++ compiler
208 // shall understand the memcpies as type punning and it shall optimize them out.
209#if 1
210 using ulp_cmp_type = boost::polygon::detail::ulp_comparison<double>;
211 ulp_cmp_type ulp_cmp;
212 static constexpr int ULPS = boost::polygon::voronoi_diagram_traits<double>::vertex_equality_predicate_type::ULPS;
213 return ulp_cmp(vertex.x(), double(ipt.x()), ULPS) == ulp_cmp_type::EQUAL &&
214 ulp_cmp(vertex.y(), double(ipt.y()), ULPS) == ulp_cmp_type::EQUAL;
215#else
216 volatile double u = static_cast<double>(ipt.x());
217 volatile double v = vertex.x();
218 if (u != v)
219 return false;
220 u = static_cast<double>(ipt.y());
221 v = vertex.y();
222 return u == v;
223#endif
224 };

Referenced by Slic3r::Voronoi::annotate_inside_outside(), on_site(), and vertex_equal_to_point().

+ Here is the caller graph for this function: