Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::Arachne::VoronoiUtils Class Reference

#include <src/libslic3r/Arachne/utils/VoronoiUtils.hpp>

Public Types

using Segment = PolygonsSegmentIndex
 
using voronoi_data_t = double
 
using vd_t = boost::polygon::voronoi_diagram< voronoi_data_t >
 

Static Public Member Functions

static Point getSourcePoint (const vd_t::cell_type &cell, const std::vector< Segment > &segments)
 
static const SegmentgetSourceSegment (const vd_t::cell_type &cell, const std::vector< Segment > &segments)
 
static PolygonsPointIndex getSourcePointIndex (const vd_t::cell_type &cell, const std::vector< Segment > &segments)
 
static Vec2i64 p (const vd_t::vertex_type *node)
 
static Points discretizeParabola (const Point &source_point, const Segment &source_segment, Point start, Point end, coord_t approximate_step_size, float transitioning_angle)
 
static bool is_finite (const VoronoiUtils::vd_t::vertex_type &vertex)
 

Detailed Description

Member Typedef Documentation

◆ Segment

◆ vd_t

using Slic3r::Arachne::VoronoiUtils::vd_t = boost::polygon::voronoi_diagram<voronoi_data_t>

◆ voronoi_data_t

Member Function Documentation

◆ discretizeParabola()

Points Slic3r::Arachne::VoronoiUtils::discretizeParabola ( const Point source_point,
const Segment source_segment,
Point  start,
Point  end,
coord_t  approximate_step_size,
float  transitioning_angle 
)
static

Discretize a parabola based on (approximate) step size. The approximate_step_size is measured parallel to the source_segment, not along the parabola.

142{
143 Points discretized;
144 // x is distance of point projected on the segment ab
145 // xx is point projected on the segment ab
146 const Point a = segment.from();
147 const Point b = segment.to();
148 const Point ab = b - a;
149 const Point as = s - a;
150 const Point ae = e - a;
151 const coord_t ab_size = ab.cast<int64_t>().norm();
152 const coord_t sx = as.cast<int64_t>().dot(ab.cast<int64_t>()) / ab_size;
153 const coord_t ex = ae.cast<int64_t>().dot(ab.cast<int64_t>()) / ab_size;
154 const coord_t sxex = ex - sx;
155
156 assert((as.cast<int64_t>().dot(ab.cast<int64_t>()) / int64_t(ab_size)) <= std::numeric_limits<coord_t>::max());
157 assert((ae.cast<int64_t>().dot(ab.cast<int64_t>()) / int64_t(ab_size)) <= std::numeric_limits<coord_t>::max());
158
159 const Point ap = p - a;
160 const coord_t px = ap.cast<int64_t>().dot(ab.cast<int64_t>()) / ab_size;
161
162 assert((ap.cast<int64_t>().dot(ab.cast<int64_t>()) / int64_t(ab_size)) <= std::numeric_limits<coord_t>::max());
163
164 Point pxx;
165 Line(a, b).distance_to_infinite_squared(p, &pxx);
166 const Point ppxx = pxx - p;
167 const coord_t d = ppxx.cast<int64_t>().norm();
168 const PointMatrix rot = PointMatrix(perp(ppxx));
169
170 if (d == 0)
171 {
172 discretized.emplace_back(s);
173 discretized.emplace_back(e);
174 return discretized;
175 }
176
177 const float marking_bound = atan(transitioning_angle * 0.5);
178 int64_t msx = - marking_bound * int64_t(d); // projected marking_start
179 int64_t mex = marking_bound * int64_t(d); // projected marking_end
180
181 assert(msx <= std::numeric_limits<coord_t>::max());
182 assert(double(msx) * double(msx) <= double(std::numeric_limits<int64_t>::max()));
183 assert(mex <= std::numeric_limits<coord_t>::max());
184 assert(double(msx) * double(msx) / double(2 * d) + double(d / 2) <= std::numeric_limits<coord_t>::max());
185
186 const coord_t marking_start_end_h = msx * msx / (2 * d) + d / 2;
187 Point marking_start = rot.unapply(Point(coord_t(msx), marking_start_end_h)) + pxx;
188 Point marking_end = rot.unapply(Point(coord_t(mex), marking_start_end_h)) + pxx;
189 const int dir = (sx > ex) ? -1 : 1;
190 if (dir < 0)
191 {
192 std::swap(marking_start, marking_end);
193 std::swap(msx, mex);
194 }
195
196 bool add_marking_start = msx * int64_t(dir) > int64_t(sx - px) * int64_t(dir) && msx * int64_t(dir) < int64_t(ex - px) * int64_t(dir);
197 bool add_marking_end = mex * int64_t(dir) > int64_t(sx - px) * int64_t(dir) && mex * int64_t(dir) < int64_t(ex - px) * int64_t(dir);
198
199 const Point apex = rot.unapply(Point(0, d / 2)) + pxx;
200 bool add_apex = int64_t(sx - px) * int64_t(dir) < 0 && int64_t(ex - px) * int64_t(dir) > 0;
201
202 assert(!(add_marking_start && add_marking_end) || add_apex);
203 if(add_marking_start && add_marking_end && !add_apex)
204 {
205 BOOST_LOG_TRIVIAL(warning) << "Failing to discretize parabola! Must add an apex or one of the endpoints.";
206 }
207
208 const coord_t step_count = static_cast<coord_t>(static_cast<float>(std::abs(ex - sx)) / approximate_step_size + 0.5);
209
210 discretized.emplace_back(s);
211 for (coord_t step = 1; step < step_count; step++)
212 {
213 assert(double(sxex) * double(step) <= double(std::numeric_limits<int64_t>::max()));
214 const int64_t x = int64_t(sx) + int64_t(sxex) * int64_t(step) / int64_t(step_count) - int64_t(px);
215 assert(double(x) * double(x) <= double(std::numeric_limits<int64_t>::max()));
216 assert(double(x) * double(x) / double(2 * d) + double(d / 2) <= double(std::numeric_limits<int64_t>::max()));
217 const int64_t y = int64_t(x) * int64_t(x) / int64_t(2 * d) + int64_t(d / 2);
218
219 if (add_marking_start && msx * int64_t(dir) < int64_t(x) * int64_t(dir))
220 {
221 discretized.emplace_back(marking_start);
222 add_marking_start = false;
223 }
224 if (add_apex && int64_t(x) * int64_t(dir) > 0)
225 {
226 discretized.emplace_back(apex);
227 add_apex = false; // only add the apex just before the
228 }
229 if (add_marking_end && mex * int64_t(dir) < int64_t(x) * int64_t(dir))
230 {
231 discretized.emplace_back(marking_end);
232 add_marking_end = false;
233 }
234 assert(x <= std::numeric_limits<coord_t>::max() && x >= std::numeric_limits<coord_t>::lowest());
235 assert(y <= std::numeric_limits<coord_t>::max() && y >= std::numeric_limits<coord_t>::lowest());
236 const Point result = rot.unapply(Point(x, y)) + pxx;
237 discretized.emplace_back(result);
238 }
239 if (add_apex)
240 {
241 discretized.emplace_back(apex);
242 }
243 if (add_marking_end)
244 {
245 discretized.emplace_back(marking_end);
246 }
247 discretized.emplace_back(e);
248 return discretized;
249}
EIGEN_DEVICE_FUNC const AtanReturnType atan() const
Definition ArrayCwiseUnaryOps.h:248
EIGEN_DEVICE_FUNC SegmentReturnType segment(Index start, Index n)
This is the const version of segment(Index,Index).
Definition BlockMethods.h:888
static Vec2i64 p(const vd_t::vertex_type *node)
Definition VoronoiUtils.cpp:14
int32_t coord_t
Definition libslic3r.h:39
const Scalar & y
Definition MathFunctions.h:552
Eigen::Matrix< typename Derived::Scalar, 2, 1, Eigen::DontAlign > perp(const Eigen::MatrixBase< Derived > &v)
Definition Point.hpp:104
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:143
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:58
TCoord< P > x(const P &p)
Definition geometry_traits.hpp:297
Coord step(const Coord &crd, Dir d)
Definition MarchingSquares.hpp:137
Kernel::Point_2 Point
Definition point_areas.cpp:20
__int64 int64_t
Definition unistd.h:76

References atan(), Slic3r::Line::distance_to_infinite_squared(), Slic3r::dot(), p(), Slic3r::perp(), segment(), and Slic3r::Arachne::PointMatrix::unapply().

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::discretize().

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

◆ getSourcePoint()

Point Slic3r::Arachne::VoronoiUtils::getSourcePoint ( const vd_t::cell_type &  cell,
const std::vector< Segment > &  segments 
)
static
25{
26 assert(cell.contains_point());
27 if(!cell.contains_point())
28 BOOST_LOG_TRIVIAL(debug) << "Voronoi cell doesn't contain a source point!";
29
30 switch (cell.source_category()) {
31 case boost::polygon::SOURCE_CATEGORY_SINGLE_POINT:
32 assert(false && "Voronoi diagram is always constructed using segments, so cell.source_category() shouldn't be SOURCE_CATEGORY_SINGLE_POINT!\n");
33 BOOST_LOG_TRIVIAL(error) << "Voronoi diagram is always constructed using segments, so cell.source_category() shouldn't be SOURCE_CATEGORY_SINGLE_POINT!";
34 break;
35 case boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT:
36 assert(cell.source_index() < segments.size());
37 return segments[cell.source_index()].to();
38 break;
39 case boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT:
40 assert(cell.source_index() < segments.size());
41 return segments[cell.source_index()].from();
42 break;
43 default:
44 assert(false && "getSourcePoint should only be called on point cells!\n");
45 break;
46 }
47
48 assert(false && "cell.source_category() is equal to an invalid value!\n");
49 BOOST_LOG_TRIVIAL(error) << "cell.source_category() is equal to an invalid value!";
50 return {};
51}
static char error[256]
Definition tga.cpp:50

References error.

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::computePointCellRange(), Slic3r::Arachne::SkeletalTrapezoidation::discretize(), and Slic3r::Geometry::get_parabolic_segment().

+ Here is the caller graph for this function:

◆ getSourcePointIndex()

PolygonsPointIndex Slic3r::Arachne::VoronoiUtils::getSourcePointIndex ( const vd_t::cell_type &  cell,
const std::vector< Segment > &  segments 
)
static
54{
55 assert(cell.contains_point());
56 if(!cell.contains_point())
57 BOOST_LOG_TRIVIAL(debug) << "Voronoi cell doesn't contain a source point!";
58
59 assert(cell.source_category() != boost::polygon::SOURCE_CATEGORY_SINGLE_POINT);
60 switch (cell.source_category()) {
61 case boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT: {
62 assert(cell.source_index() < segments.size());
63 PolygonsPointIndex ret = segments[cell.source_index()];
64 ++ret;
65 return ret;
66 break;
67 }
68 case boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT: {
69 assert(cell.source_index() < segments.size());
70 return segments[cell.source_index()];
71 break;
72 }
73 default:
74 assert(false && "getSourcePoint should only be called on point cells!\n");
75 break;
76 }
77 PolygonsPointIndex ret = segments[cell.source_index()];
78 return ++ret;
79}
PathsPointIndex< Polygons > PolygonsPointIndex
Definition PolygonsPointIndex.hpp:130

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::computePointCellRange().

+ Here is the caller graph for this function:

◆ getSourceSegment()

const VoronoiUtils::Segment & Slic3r::Arachne::VoronoiUtils::getSourceSegment ( const vd_t::cell_type &  cell,
const std::vector< Segment > &  segments 
)
static
82{
83 assert(cell.contains_segment());
84 if (!cell.contains_segment())
85 BOOST_LOG_TRIVIAL(debug) << "Voronoi cell doesn't contain a source segment!";
86
87 return segments[cell.source_index()];
88}

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::computeSegmentCellRange(), Slic3r::Arachne::detect_missing_voronoi_vertex(), Slic3r::Arachne::SkeletalTrapezoidation::discretize(), and Slic3r::Geometry::get_parabolic_segment().

+ Here is the caller graph for this function:

◆ is_finite()

static bool Slic3r::Arachne::VoronoiUtils::is_finite ( const VoronoiUtils::vd_t::vertex_type &  vertex)
inlinestatic
40 {
41 return std::isfinite(vertex.x()) && std::isfinite(vertex.y());
42 }
TPoint< S > & vertex(S &sh, unsigned long idx, const PolygonTag &)
Definition geometry_traits.hpp:1180

Referenced by Slic3r::Arachne::detect_missing_voronoi_vertex(), Slic3r::Arachne::has_finite_edge_with_non_finite_vertex(), Slic3r::Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(), and Slic3r::Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection().

+ Here is the caller graph for this function:

◆ p()

Vec2i64 Slic3r::Arachne::VoronoiUtils::p ( const vd_t::vertex_type *  node)
static
15{
16 const double x = node->x();
17 const double y = node->y();
18 assert(std::isfinite(x) && std::isfinite(y));
19 assert(x <= double(std::numeric_limits<int64_t>::max()) && x >= std::numeric_limits<int64_t>::lowest());
20 assert(y <= double(std::numeric_limits<int64_t>::max()) && y >= std::numeric_limits<int64_t>::lowest());
21 return {int64_t(x + 0.5 - (x < 0)), int64_t(y + 0.5 - (y < 0))}; // Round to the nearest integer coordinates.
22}

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::computePointCellRange(), Slic3r::Arachne::SkeletalTrapezoidation::computeSegmentCellRange(), Slic3r::Arachne::SkeletalTrapezoidation::constructFromPolygons(), Slic3r::Arachne::detect_missing_voronoi_vertex(), Slic3r::Arachne::SkeletalTrapezoidation::discretize(), and discretizeParabola().

+ Here is the caller graph for this function:

The documentation for this class was generated from the following files: