OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::Arachne Namespace Reference

Namespaces

namespace  LinearAlg2D

Classes

class  BeadingStrategy
class  BeadingStrategyFactory
class  DistributedBeadingStrategy
class  LimitedBeadingStrategy
class  OuterWallInsetBeadingStrategy
class  RedistributeBeadingStrategy
class  WideningBeadingStrategy
class  SkeletalTrapezoidation
class  SkeletalTrapezoidationEdge
class  STHalfEdge
class  STHalfEdgeNode
class  SkeletalTrapezoidationGraph
class  SkeletalTrapezoidationJoint
struct  ExtrusionJunction
struct  ExtrusionLine
class  HalfEdgeNode
class  HalfEdge
class  HalfEdgeGraph
class  PathsPointIndex
struct  PolygonsPointIndexSegmentLocator
struct  PathsPointIndexLocator
class  PolygonsSegmentIndex
class  PolylineStitcher
class  SparseGrid
 Sparse grid which can locate spatially nearby elements efficiently. More...
class  SparseLineGrid
 Sparse grid which can locate spatially nearby elements efficiently. More...
class  SparsePointGrid
 Sparse grid which can locate spatially nearby elements efficiently. More...
class  SquareGrid
class  WallToolPathsParams
class  WallToolPaths

Typedefs

using BeadingStrategyPtr = std::unique_ptr<BeadingStrategy>
using VD = Slic3r::Geometry::VoronoiDiagram
using LineJunctions = std::vector<ExtrusionJunction>
using ExtrusionJunctions = std::vector<ExtrusionJunction>
using VariableWidthLines = std::vector<ExtrusionLine>
using PolygonsPointIndex = PathsPointIndex<Polygons>
typedef SparseLineGrid< PolygonsPointIndex, PolygonsPointIndexSegmentLocator > LocToLineGrid

Functions

template<typename T>
constexpr T pi_div (const T div)
static Point normal (const Point &p0, coord_t len)
Point operator- (const ExtrusionJunction &a, const ExtrusionJunction &b)
const Point & make_point (const ExtrusionJunction &ej)
coord_t colinear_vertex_tolerance ()
template<class PathType>
static Slic3r::ThickPolyline to_thick_polyline (const PathType &path)
static Polygon to_polygon (const ExtrusionLine &line)
static Points to_points (const ExtrusionLine &extrusion_line)
const Point & make_point (const Point &p)
WallToolPathsParams make_paths_params (const int layer_id, const PrintObjectConfig &print_object_config, const PrintConfig &print_config)
void simplify (Polygon &thiss, const int64_t smallest_line_segment_squared, const int64_t allowed_error_distance_squared)
void simplify (Polygons &thiss, const int64_t smallest_line_segment=scaled< coord_t >(0.01), const int64_t allowed_error_distance=scaled< coord_t >(0.005))
std::unique_ptr< LocToLineGrid > createLocToLineGrid (const Polygons &polygons, int square_size)
void fixSelfIntersections (const coord_t epsilon, Polygons &thiss)
void removeDegenerateVerts (Polygons &thiss)
void removeSmallAreas (Polygons &thiss, const double min_area_size, const bool remove_holes)
void removeColinearEdges (Polygon &poly, const double max_deviation_angle)
void removeColinearEdges (Polygons &thiss, const double max_deviation_angle=0.0005)
template<typename T>
bool shorterThan (const T &shape, const coord_t check_length)
coord_t meshfix_maximum_resolution ()
coord_t meshfix_maximum_deviation ()
coord_t meshfix_maximum_extrusion_area_deviation ()

Variables

constexpr bool fill_outline_gaps = true

Class Documentation

◆ Slic3r::Arachne::HalfEdgeGraph

class Slic3r::Arachne::HalfEdgeGraph
template<class node_data_t, class edge_data_t, class derived_node_t, class derived_edge_t>
class Slic3r::Arachne::HalfEdgeGraph< node_data_t, edge_data_t, derived_node_t, derived_edge_t >
Inheritance diagram for Slic3r::Arachne::HalfEdgeGraph< node_data_t, edge_data_t, derived_node_t, derived_edge_t >:
Collaboration diagram for Slic3r::Arachne::HalfEdgeGraph< node_data_t, edge_data_t, derived_node_t, derived_edge_t >:
Class Members
typedef derived_edge_t edge_t derived_edge_t
typedef list< edge_t > Edges std::list<edge_t>
typedef derived_node_t node_t derived_node_t
typedef list< node_t > Nodes std::list<node_t>
Class Members
Edges edges
Nodes nodes

◆ Slic3r::Arachne::WallToolPathsParams

class Slic3r::Arachne::WallToolPathsParams
Class Members
bool is_top_or_bottom_layer = false
float min_bead_width = 0.f
float min_feature_size = 0.f
float min_length_factor = 0.5f
int wall_distribution_count = 1
coord_t wall_maximum_deviation = meshfix_maximum_deviation()
coord_t wall_maximum_resolution = meshfix_maximum_resolution()
float wall_transition_angle = 10.f
float wall_transition_filter_deviation = 0.f
float wall_transition_length = 0.f

Typedef Documentation

◆ BeadingStrategyPtr

◆ ExtrusionJunctions

◆ LineJunctions

◆ LocToLineGrid

◆ PolygonsPointIndex

◆ VariableWidthLines

◆ VD

Function Documentation

◆ colinear_vertex_tolerance()

coord_t Slic3r::Arachne::colinear_vertex_tolerance ( )
inline
40{ return coord_t(SCALED_EPSILON); }
#define SCALED_EPSILON
Definition libslic3r.h:109
int64_t coord_t
Definition libslic3r.h:48

References SCALED_EPSILON.

Referenced by Slic3r::Arachne::ExtrusionLine::simplify(), and simplify().

Here is the caller graph for this function:

◆ createLocToLineGrid()

std::unique_ptr< LocToLineGrid > Slic3r::Arachne::createLocToLineGrid ( const Polygons & polygons,
int square_size )
270{
271 unsigned int n_points = 0;
272 for (const auto &poly : polygons)
273 n_points += poly.size();
274
275 auto ret = std::make_unique<LocToLineGrid>(square_size, n_points);
276
277 for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++)
278 for (unsigned int point_idx = 0; point_idx < polygons[poly_idx].size(); point_idx++)
279 ret->insert(PolygonsPointIndex(&polygons, poly_idx, point_idx));
280 return ret;
281}
PathsPointIndex< Polygons > PolygonsPointIndex
Definition PolygonsPointIndex.hpp:133

Referenced by fixSelfIntersections().

Here is the caller graph for this function:

◆ fixSelfIntersections()

void Slic3r::Arachne::fixSelfIntersections ( const coord_t epsilon,
Polygons & thiss )
286{
287 if (epsilon < 1)
288 return;
289
290 const int64_t half_epsilon = (epsilon + 1) / 2;
291
292 // Points too close to line segments should be moved a little away from those line segments, but less than epsilon,
293 // so at least half-epsilon distance between points can still be guaranteed.
294 const coord_t grid_size = scaled<coord_t>(2.);
295 auto query_grid = createLocToLineGrid(thiss, grid_size);
296
297 const auto move_dist = std::max<int64_t>(2L, half_epsilon - 2);
298 const int64_t half_epsilon_sqrd = half_epsilon * half_epsilon;
299
300 const size_t n = thiss.size();
301 for (size_t poly_idx = 0; poly_idx < n; poly_idx++) {
302 const size_t pathlen = thiss[poly_idx].size();
303 for (size_t point_idx = 0; point_idx < pathlen; ++point_idx) {
304 Point &pt = thiss[poly_idx][point_idx];
305 for (const auto &line : query_grid->getNearby(pt, epsilon)) {
306 const size_t line_next_idx = (line.point_idx + 1) % thiss[line.poly_idx].size();
307 if (poly_idx == line.poly_idx && (point_idx == line.point_idx || point_idx == line_next_idx))
308 continue;
309
310 const Line segment(thiss[line.poly_idx][line.point_idx], thiss[line.poly_idx][line_next_idx]);
311 Point segment_closest_point;
312 segment.distance_to_squared(pt, &segment_closest_point);
313
314 if (half_epsilon_sqrd >= (pt - segment_closest_point).cast<int64_t>().squaredNorm()) {
315 const Point &other = thiss[poly_idx][(point_idx + 1) % pathlen];
316 const Vec2i64 vec = (LinearAlg2D::pointIsLeftOfLine(other, segment.a, segment.b) > 0 ? segment.b - segment.a : segment.a - segment.b).cast<int64_t>();
317 assert(Slic3r::sqr(double(vec.x())) < double(std::numeric_limits<int64_t>::max()));
318 assert(Slic3r::sqr(double(vec.y())) < double(std::numeric_limits<int64_t>::max()));
319 const int64_t len = vec.norm();
320 pt.x() += (-vec.y() * move_dist) / len;
321 pt.y() += (vec.x() * move_dist) / len;
322 }
323 }
324 }
325 }
326}
Definition Line.hpp:156
Definition Point.hpp:199
static int64_t pointIsLeftOfLine(const Point &p, const Point &a, const Point &b)
Definition linearAlg2D.hpp:26
std::unique_ptr< LocToLineGrid > createLocToLineGrid(const Polygons &polygons, int square_size)
Definition WallToolPaths.cpp:269
BoundingBox scaled(const BoundingBoxf &bb)
Definition BoundingBox.hpp:284
constexpr T sqr(T x)
Definition libslic3r.h:301
Eigen::Matrix< int64_t, 2, 1, Eigen::DontAlign > Vec2i64
Definition Point.hpp:58
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299

References Slic3r::cast(), createLocToLineGrid(), Slic3r::Arachne::LinearAlg2D::pointIsLeftOfLine(), Slic3r::scaled(), and Slic3r::sqr().

Referenced by Slic3r::Arachne::WallToolPaths::generate().

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

◆ make_paths_params()

WallToolPathsParams Slic3r::Arachne::make_paths_params ( const int layer_id,
const PrintObjectConfig & print_object_config,
const PrintConfig & print_config )
48{
49 WallToolPathsParams input_params;
50 {
51 const double min_nozzle_diameter = *std::min_element(print_config.nozzle_diameter.values.begin(), print_config.nozzle_diameter.values.end());
52 if (const auto &min_feature_size_opt = print_object_config.min_feature_size)
53 input_params.min_feature_size = min_feature_size_opt.value * 0.01 * min_nozzle_diameter;
54
55 if (const auto &min_wall_length_factor_opt = print_object_config.min_length_factor)
56 input_params.min_length_factor = min_wall_length_factor_opt.value;
57 else
58 input_params.min_length_factor = 0.5f;
59
60 if (layer_id == 0) {
61 if (const auto &initial_layer_min_bead_width_opt = print_object_config.initial_layer_min_bead_width)
62 input_params.min_bead_width = initial_layer_min_bead_width_opt.value * 0.01 * min_nozzle_diameter;
63 } else {
64 if (const auto &min_bead_width_opt = print_object_config.min_bead_width)
65 input_params.min_bead_width = min_bead_width_opt.value * 0.01 * min_nozzle_diameter;
66 }
67
68 if (const auto &wall_transition_filter_deviation_opt = print_object_config.wall_transition_filter_deviation)
69 input_params.wall_transition_filter_deviation = wall_transition_filter_deviation_opt.value * 0.01 * min_nozzle_diameter;
70
71 if (const auto &wall_transition_length_opt = print_object_config.wall_transition_length)
72 input_params.wall_transition_length = wall_transition_length_opt.value * 0.01 * min_nozzle_diameter;
73
74 input_params.wall_transition_angle = print_object_config.wall_transition_angle.value;
75 input_params.wall_distribution_count = print_object_config.wall_distribution_count.value;
76
77 input_params.is_top_or_bottom_layer = false; // Set to default value
78
79 if (const auto& wall_maximum_resolution_opt = print_object_config.wall_maximum_resolution)
80 input_params.wall_maximum_resolution = scaled<coord_t>(wall_maximum_resolution_opt.value);
81
82 if (const auto& wall_maximum_deviation_opt = print_object_config.wall_maximum_deviation)
83 input_params.wall_maximum_deviation = scaled<coord_t>(wall_maximum_deviation_opt.value);
84 }
85
86 return input_params;
87}
float wall_transition_filter_deviation
Definition WallToolPaths.hpp:36
float min_length_factor
Definition WallToolPaths.hpp:33
bool is_top_or_bottom_layer
Definition WallToolPaths.hpp:38
coord_t wall_maximum_deviation
Definition WallToolPaths.hpp:41
float wall_transition_angle
Definition WallToolPaths.hpp:35
coord_t wall_maximum_resolution
Definition WallToolPaths.hpp:40
float wall_transition_length
Definition WallToolPaths.hpp:34
float min_feature_size
Definition WallToolPaths.hpp:32
float min_bead_width
Definition WallToolPaths.hpp:31
int wall_distribution_count
Definition WallToolPaths.hpp:37
Definition WallToolPaths.hpp:29

References Slic3r::Arachne::WallToolPathsParams::is_top_or_bottom_layer, Slic3r::Arachne::WallToolPathsParams::min_bead_width, Slic3r::Arachne::WallToolPathsParams::min_feature_size, Slic3r::Arachne::WallToolPathsParams::min_length_factor, Slic3r::PrintObjectConfig, Slic3r::scaled(), Slic3r::Arachne::WallToolPathsParams::wall_distribution_count, Slic3r::Arachne::WallToolPathsParams::wall_maximum_deviation, Slic3r::Arachne::WallToolPathsParams::wall_maximum_resolution, Slic3r::Arachne::WallToolPathsParams::wall_transition_angle, Slic3r::Arachne::WallToolPathsParams::wall_transition_filter_deviation, and Slic3r::Arachne::WallToolPathsParams::wall_transition_length.

Referenced by Slic3r::PerimeterGenerator::printable_slices().

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

◆ make_point() [1/2]

const Point & Slic3r::Arachne::make_point ( const ExtrusionJunction & ej)
inline
61{
62 return ej.p;
63}
Point p
Definition ExtrusionJunction.hpp:28

References Slic3r::Arachne::ExtrusionJunction::p.

Referenced by Slic3r::Arachne::PathsPointIndexLocator< Paths >::operator()(), Slic3r::Arachne::PathsPointIndex< Polygons >::p(), and Slic3r::Arachne::PolylineStitcher< Paths, Path, Junction >::stitch().

Here is the caller graph for this function:

◆ make_point() [2/2]

const Point & Slic3r::Arachne::make_point ( const Point & p)
inline
20{ return p; }

◆ meshfix_maximum_deviation()

coord_t Slic3r::Arachne::meshfix_maximum_deviation ( )
inline
25{ return scaled<coord_t>(0.025); }

References Slic3r::scaled().

Here is the call graph for this function:

◆ meshfix_maximum_extrusion_area_deviation()

coord_t Slic3r::Arachne::meshfix_maximum_extrusion_area_deviation ( )
inline
26{ return scaled<coord_t>(2.); }

References Slic3r::scaled().

Referenced by Slic3r::Arachne::WallToolPaths::simplifyToolPaths().

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

◆ meshfix_maximum_resolution()

coord_t Slic3r::Arachne::meshfix_maximum_resolution ( )
inline
24{ return scaled<coord_t>(0.5); }

References Slic3r::scaled().

Here is the call graph for this function:

◆ normal()

Point Slic3r::Arachne::normal ( const Point & p0,
coord_t len )
inlinestatic
1270{
1271 int64_t _len = p0.cast<int64_t>().norm();
1272 if (_len < 1)
1273 return Point(len, 0);
1274 return (p0.cast<int64_t>() * int64_t(len) / _len).cast<coord_t>();
1275};

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::applyTransitions(), and Slic3r::Arachne::SkeletalTrapezoidation::generateExtraRibs().

Here is the caller graph for this function:

◆ operator-()

Point Slic3r::Arachne::operator- ( const ExtrusionJunction & a,
const ExtrusionJunction & b )
inline
55{
56 return a.p - b.p;
57}

References Slic3r::Arachne::ExtrusionJunction::p.

◆ pi_div()

template<typename T>
T Slic3r::Arachne::pi_div ( const T div)
constexpr
18{ return static_cast<T>(M_PI) / div; }
#define M_PI
Definition ExtrusionSimulator.cpp:31

References M_PI.

◆ removeColinearEdges() [1/2]

void Slic3r::Arachne::removeColinearEdges ( Polygon & poly,
const double max_deviation_angle )
418{
419 // TODO: Can be made more efficient (for example, use pointer-types for process-/skip-indices, so we can swap them without copy).
420 size_t num_removed_in_iteration = 0;
421 do {
422 num_removed_in_iteration = 0;
423 std::vector<bool> process_indices(poly.points.size(), true);
424
425 bool go = true;
426 while (go) {
427 go = false;
428
429 const auto &rpath = poly;
430 const size_t pathlen = rpath.size();
431 if (pathlen <= 3)
432 return;
433
434 std::vector<bool> skip_indices(poly.points.size(), false);
435
436 Polygon new_path;
437 for (size_t point_idx = 0; point_idx < pathlen; ++point_idx) {
438 // Don't iterate directly over process-indices, but do it this way, because there are points _in_ process-indices that should nonetheless
439 // be skipped:
440 if (!process_indices[point_idx]) {
441 new_path.points.push_back(rpath[point_idx]);
442 continue;
443 }
444
445 // Should skip the last point for this iteration if the old first was removed (which can be seen from the fact that the new first was skipped):
446 if (point_idx == (pathlen - 1) && skip_indices[0]) {
447 skip_indices[new_path.size()] = true;
448 go = true;
449 new_path.points.push_back(rpath[point_idx]);
450 break;
451 }
452
453 const Point &prev = rpath[(point_idx - 1 + pathlen) % pathlen];
454 const Point &pt = rpath[point_idx];
455 const Point &next = rpath[(point_idx + 1) % pathlen];
456
457 float angle = LinearAlg2D::getAngleLeft(prev, pt, next); // [0 : 2 * pi]
458 if (angle >= float(M_PI)) { angle -= float(M_PI); } // map [pi : 2 * pi] to [0 : pi]
459
460 // Check if the angle is within limits for the point to 'make sense', given the maximum deviation.
461 // If the angle indicates near-parallel segments ignore the point 'pt'
462 if (angle > max_deviation_angle && angle < M_PI - max_deviation_angle) {
463 new_path.points.push_back(pt);
464 } else if (point_idx != (pathlen - 1)) {
465 // Skip the next point, since the current one was removed:
466 skip_indices[new_path.size()] = true;
467 go = true;
468 new_path.points.push_back(next);
469 ++point_idx;
470 }
471 }
472 poly = new_path;
473 num_removed_in_iteration += pathlen - poly.points.size();
474
475 process_indices.clear();
476 process_indices.insert(process_indices.end(), skip_indices.begin(), skip_indices.end());
477 }
478 } while (num_removed_in_iteration > 0);
479}
Points points
Definition MultiPoint.hpp:22
size_t size() const
Definition MultiPoint.hpp:50
Definition Polygon.hpp:31
static float getAngleLeft(const Point &a, const Point &b, const Point &c)
Definition linearAlg2D.hpp:48
void poly(std::vector< std::pair< Vec2d, Vec2d > > &out, std::initializer_list< Vec2d > p)
Definition DesignSketchTool.cpp:7751
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:138

References Slic3r::angle(), Slic3r::Arachne::LinearAlg2D::getAngleLeft(), M_PI, Slic3r::MultiPoint::points, and Slic3r::MultiPoint::size().

Referenced by Slic3r::Arachne::WallToolPaths::generate(), and removeColinearEdges().

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

◆ removeColinearEdges() [2/2]

void Slic3r::Arachne::removeColinearEdges ( Polygons & thiss,
const double max_deviation_angle = 0.0005 )
482{
483 for (int p = 0; p < int(thiss.size()); p++) {
484 removeColinearEdges(thiss[p], max_deviation_angle);
485 if (thiss[p].size() < 3) {
486 thiss.erase(thiss.begin() + p);
487 p--;
488 }
489 }
490}
void removeColinearEdges(Polygon &poly, const double max_deviation_angle)
Definition WallToolPaths.cpp:417

References removeColinearEdges().

Here is the call graph for this function:

◆ removeDegenerateVerts()

void Slic3r::Arachne::removeDegenerateVerts ( Polygons & thiss)

Removes overlapping consecutive line segments which don't delimit a positive area.

332{
333 for (size_t poly_idx = 0; poly_idx < thiss.size(); poly_idx++) {
334 Polygon &poly = thiss[poly_idx];
335 Polygon result;
336
337 auto isDegenerate = [](const Point &last, const Point &now, const Point &next) {
338 Vec2i64 last_line = (now - last).cast<int64_t>();
339 Vec2i64 next_line = (next - now).cast<int64_t>();
340 return last_line.dot(next_line) == -1 * last_line.norm() * next_line.norm();
341 };
342 bool isChanged = false;
343 for (size_t idx = 0; idx < poly.size(); idx++) {
344 const Point &last = (result.size() == 0) ? poly.back() : result.back();
345 if (idx + 1 == poly.size() && result.size() == 0)
346 break;
347
348 const Point &next = (idx + 1 == poly.size()) ? result[0] : poly[idx + 1];
349 if (isDegenerate(last, poly[idx], next)) { // lines are in the opposite direction
350 // don't add vert to the result
351 isChanged = true;
352 while (result.size() > 1 && isDegenerate(result[result.size() - 2], result.back(), next))
353 result.points.pop_back();
354 } else {
355 result.points.emplace_back(poly[idx]);
356 }
357 }
358
359 if (isChanged) {
360 if (result.size() > 2) {
361 poly = result;
362 } else {
363 thiss.erase(thiss.begin() + poly_idx);
364 poly_idx--; // effectively the next iteration has the same poly_idx (referring to a new poly which is not yet processed)
365 }
366 }
367 }
368}
const Point & back() const
Definition MultiPoint.hpp:46

References Slic3r::MultiPoint::back(), Slic3r::cast(), Slic3r::MultiPoint::points, and Slic3r::MultiPoint::size().

Referenced by Slic3r::Arachne::WallToolPaths::generate().

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

◆ removeSmallAreas()

void Slic3r::Arachne::removeSmallAreas ( Polygons & thiss,
const double min_area_size,
const bool remove_holes )
371{
372 auto new_end = thiss.end();
373 if (remove_holes) {
374 for (auto it = thiss.begin(); it < new_end;) {
375 // All polygons smaller than target are removed by replacing them with a polygon from the back of the vector.
376 if (fabs(it->area()) < min_area_size) {
377 --new_end;
378 *it = std::move(*new_end);
379 continue; // Don't increment the iterator such that the polygon just swapped in is checked next.
380 }
381 ++it;
382 }
383 } else {
384 // For each polygon, computes the signed area, move small outlines at the end of the vector and keep pointer on small holes
385 Polygons small_holes;
386 for (auto it = thiss.begin(); it < new_end;) {
387 if (double area = it->area(); fabs(area) < min_area_size) {
388 if (area >= 0) {
389 --new_end;
390 if (it < new_end) {
391 std::swap(*new_end, *it);
392 continue;
393 } else { // Don't self-swap the last Path
394 break;
395 }
396 } else {
397 small_holes.push_back(*it);
398 }
399 }
400 ++it;
401 }
402
403 // Removes small holes that have their first point inside one of the removed outlines
404 // Iterating in reverse ensures that unprocessed small holes won't be moved
405 const auto removed_outlines_start = new_end;
406 for (auto hole_it = small_holes.rbegin(); hole_it < small_holes.rend(); hole_it++)
407 for (auto outline_it = removed_outlines_start; outline_it < thiss.end(); outline_it++)
408 if (Polygon(*outline_it).contains(*hole_it->begin())) {
409 new_end--;
410 *hole_it = std::move(*new_end);
411 break;
412 }
413 }
414 thiss.resize(new_end-thiss.begin());
415}
bool contains(const Point &point) const
Definition Polygon.hpp:73
double area(const ExPolygon &poly)
Definition ExPolygon.hpp:511
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22
Slic3r::Polygon Polygon
Definition Emboss.cpp:101

References Slic3r::area(), and Slic3r::Polygon::contains().

Referenced by Slic3r::Arachne::WallToolPaths::generate().

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

◆ shorterThan()

template<typename T>
bool Slic3r::Arachne::shorterThan ( const T & shape,
const coord_t check_length )
682{
683 const auto *p0 = &shape.back();
684 int64_t length = 0;
685 for (const auto &p1 : shape) {
686 length += (*p0 - p1).template cast<int64_t>().norm();
687 if (length >= check_length)
688 return false;
689 p0 = &p1;
690 }
691 return true;
692}
double length(const Points &pts)
Definition MultiPoint.hpp:181

References Slic3r::cast(), and Slic3r::length().

Referenced by Slic3r::Arachne::WallToolPaths::removeSmallLines().

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

◆ simplify() [1/2]

void Slic3r::Arachne::simplify ( Polygon & thiss,
const int64_t smallest_line_segment_squared,
const int64_t allowed_error_distance_squared )
108{
109 if (thiss.size() < 3) {
110 thiss.points.clear();
111 return;
112 }
113 if (thiss.size() == 3)
114 return;
115
116 Polygon new_path;
117 Point previous = thiss.points.back();
118 Point previous_previous = thiss.points.at(thiss.points.size() - 2);
119 Point current = thiss.points.at(0);
120
121 /* When removing a vertex, we check the height of the triangle of the area
122 being removed from the original polygon by the simplification. However,
123 when consecutively removing multiple vertices the height of the previously
124 removed vertices w.r.t. the shortcut path changes.
125 In order to not recompute the new height value of previously removed
126 vertices we compute the height of a representative triangle, which covers
127 the same amount of area as the area being cut off. We use the Shoelace
128 formula to accumulate the area under the removed segments. This works by
129 computing the area in a 'fan' where each of the blades of the fan go from
130 the origin to one of the segments. While removing vertices the area in
131 this fan accumulates. By subtracting the area of the blade connected to
132 the short-cutting segment we obtain the total area of the cutoff region.
133 From this area we compute the height of the representative triangle using
134 the standard formula for a triangle area: A = .5*b*h
135 */
136 int64_t accumulated_area_removed = int64_t(previous.x()) * int64_t(current.y()) - int64_t(previous.y()) * int64_t(current.x()); // Twice the Shoelace formula for area of polygon per line segment.
137
138 for (size_t point_idx = 0; point_idx < thiss.points.size(); point_idx++) {
139 current = thiss.points.at(point_idx % thiss.points.size());
140
141 //Check if the accumulated area doesn't exceed the maximum.
142 Point next;
143 if (point_idx + 1 < thiss.points.size()) {
144 next = thiss.points.at(point_idx + 1);
145 } else if (point_idx + 1 == thiss.points.size() && new_path.size() > 1) { // don't spill over if the [next] vertex will then be equal to [previous]
146 next = new_path[0]; //Spill over to new polygon for checking removed area.
147 } else {
148 next = thiss.points.at((point_idx + 1) % thiss.points.size());
149 }
150 const int64_t removed_area_next = int64_t(current.x()) * int64_t(next.y()) - int64_t(current.y()) * int64_t(next.x()); // Twice the Shoelace formula for area of polygon per line segment.
151 const int64_t negative_area_closing = int64_t(next.x()) * int64_t(previous.y()) - int64_t(next.y()) * int64_t(previous.x()); // area between the origin and the short-cutting segment
152 accumulated_area_removed += removed_area_next;
153
154 const int64_t length2 = (current - previous).cast<int64_t>().squaredNorm();
155
156 // Orca:
157 // Checking if the segment's length is smaller than 5 microns (0.005mm).
158 // The value of `length2` is scaled and squared, so we need to compare it with the squared value of 5 microns
159 if (length2 < Slic3r::sqr(scaled<coord_t>(0.005))) {
160 // We're allowed to always delete segments of less than 5 micron.
161 continue;
162 }
163
164 const int64_t area_removed_so_far = accumulated_area_removed + negative_area_closing; // close the shortcut area polygon
165 const int64_t base_length_2 = (next - previous).cast<int64_t>().squaredNorm();
166
167 if (base_length_2 == 0) //Two line segments form a line back and forth with no area.
168 continue; //Remove the vertex.
169 //We want to check if the height of the triangle formed by previous, current and next vertices is less than allowed_error_distance_squared.
170 //1/2 L = A [actual area is half of the computed shoelace value] // Shoelace formula is .5*(...) , but we simplify the computation and take out the .5
171 //A = 1/2 * b * h [triangle area formula]
172 //L = b * h [apply above two and take out the 1/2]
173 //h = L / b [divide by b]
174 //h^2 = (L / b)^2 [square it]
175 //h^2 = L^2 / b^2 [factor the divisor]
176 const int64_t height_2 = double(area_removed_so_far) * double(area_removed_so_far) / double(base_length_2);
177 // Orca: The value of `height_2` is squared, so we need to compare it with the squared value
178 if ((height_2 <= Slic3r::sqr(colinear_vertex_tolerance()) //Almost exactly colinear (barring rounding errors).
179 && Line::distance_to_infinite(current, previous, next) <= double(colinear_vertex_tolerance()))) // make sure that height_2 is not small because of cancellation of positive and negative areas
180 continue;
181
182 if (length2 < smallest_line_segment_squared
183 && height_2 <= allowed_error_distance_squared) // removing the vertex doesn't introduce too much error.)
184 {
185 const int64_t next_length2 = (current - next).cast<int64_t>().squaredNorm();
186 if (next_length2 > 4 * smallest_line_segment_squared) {
187 // Special case; The next line is long. If we were to remove this, it could happen that we get quite noticeable artifacts.
188 // We should instead move this point to a location where both edges are kept and then remove the previous point that we wanted to keep.
189 // By taking the intersection of these two lines, we get a point that preserves the direction (so it makes the corner a bit more pointy).
190 // We just need to be sure that the intersection point does not introduce an artifact itself.
191 Point intersection_point;
192 bool has_intersection = Line(previous_previous, previous).intersection_infinite(Line(current, next), &intersection_point);
193 if (!has_intersection
194 || Line::distance_to_infinite_squared(intersection_point, previous, current) > double(allowed_error_distance_squared)
195 || (intersection_point - previous).cast<int64_t>().squaredNorm() > smallest_line_segment_squared // The intersection point is way too far from the 'previous'
196 || (intersection_point - next).cast<int64_t>().squaredNorm() > smallest_line_segment_squared) // and 'next' points, so it shouldn't replace 'current'
197 {
198 // We can't find a better spot for it, but the size of the line is more than 5 micron.
199 // So the only thing we can do here is leave it in...
200 }
201 else {
202 // New point seems like a valid one.
203 current = intersection_point;
204 // If there was a previous point added, remove it.
205 if(!new_path.empty()) {
206 new_path.points.pop_back();
207 previous = previous_previous;
208 }
209 }
210 } else {
211 continue; //Remove the vertex.
212 }
213 }
214 //Don't remove the vertex.
215 accumulated_area_removed = removed_area_next; // so that in the next iteration it's the area between the origin, [previous] and [current]
216 previous_previous = previous;
217 previous = current; //Note that "previous" is only updated if we don't remove the vertex.
218 new_path.points.push_back(current);
219 }
220
221 thiss = new_path;
222}
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
bool empty() const
Definition MultiPoint.hpp:51
coord_t colinear_vertex_tolerance()
Definition ExtrusionLine.hpp:40
Kernel::Point_3 Point
Definition MeshRepair.cpp:81

References Slic3r::cast(), colinear_vertex_tolerance(), Slic3r::Line::distance_to_infinite(), Slic3r::Line::distance_to_infinite_squared(), Slic3r::MultiPoint::empty(), Slic3r::Line::intersection_infinite(), Slic3r::MultiPoint::points, Slic3r::scaled(), Slic3r::MultiPoint::size(), and Slic3r::sqr().

Referenced by Slic3r::Arachne::WallToolPaths::generate(), and simplify().

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

◆ simplify() [2/2]

void Slic3r::Arachne::simplify ( Polygons & thiss,
const int64_t smallest_line_segment = scaled<coord_t>(0.01),
const int64_t allowed_error_distance = scaled<coord_t>(0.005) )

Removes vertices of the polygons to make sure that they are not too high resolution.

This removes points 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.

Criteria:

  1. Never remove a vertex if either of the connceted segments is larger than smallest_line_segment
  2. Never remove a vertex if the distance between that vertex and the final resulting polygon would be higher than allowed_error_distance
  3. The direction of segments longer than smallest_line_segment always remains unaltered (but their end points may change if it is connected to a small segment)

Simplify uses a heuristic and doesn't neccesarily 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) colinear line segments are joined into a single line segment.

Parameters
smallest_line_segmentMaximal length of removed line segments.
allowed_error_distanceIf removing a vertex introduces a deviation from the original path that is more than this distance, the vertex may not be removed.
254{
255 const int64_t allowed_error_distance_squared = int64_t(allowed_error_distance) * int64_t(allowed_error_distance);
256 const int64_t smallest_line_segment_squared = int64_t(smallest_line_segment) * int64_t(smallest_line_segment);
257 for (size_t p = 0; p < thiss.size(); p++)
258 {
259 simplify(thiss[p], smallest_line_segment_squared, allowed_error_distance_squared);
260 if (thiss[p].size() < 3)
261 {
262 thiss.erase(thiss.begin() + p);
263 p--;
264 }
265 }
266}
void simplify(Polygon &thiss, const int64_t smallest_line_segment_squared, const int64_t allowed_error_distance_squared)
Definition WallToolPaths.cpp:107

References Slic3r::scaled(), and simplify().

Here is the call graph for this function:

◆ to_points()

Points Slic3r::Arachne::to_points ( const ExtrusionLine & extrusion_line)
static
244{
245 Points points;
246 points.reserve(extrusion_line.junctions.size());
247 for (const ExtrusionJunction &junction : extrusion_line.junctions)
248 points.emplace_back(junction.p);
249 return points;
250}
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73
Definition ExtrusionJunction.hpp:23
std::vector< ExtrusionJunction > junctions
Definition ExtrusionLine.hpp:88

References Slic3r::Arachne::ExtrusionLine::junctions, and Slic3r::Arachne::ExtrusionJunction::p.

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

Here is the caller graph for this function:

◆ to_polygon()

Polygon Slic3r::Arachne::to_polygon ( const ExtrusionLine & line)
inlinestatic
233{
234 Polygon out;
235 assert(line.junctions.size() >= 3);
236 assert(line.junctions.front().p == line.junctions.back().p);
237 out.points.reserve(line.junctions.size() - 1);
238 for (auto it = line.junctions.begin(); it != line.junctions.end() - 1; ++it)
239 out.points.emplace_back(it->p);
240 return out;
241}

References Slic3r::Arachne::ExtrusionLine::junctions, and Slic3r::MultiPoint::points.

◆ to_thick_polyline()

template<class PathType>
Slic3r::ThickPolyline Slic3r::Arachne::to_thick_polyline ( const PathType & path)
inlinestatic
213{
214 assert(path.size() >= 2);
216 out.points.emplace_back(path.front().x(), path.front().y());
217 out.width.emplace_back(path.front().z());
218 out.points.emplace_back(path[1].x(), path[1].y());
219 out.width.emplace_back(path[1].z());
220
221 auto it_prev = path.begin() + 1;
222 for (auto it = path.begin() + 2; it != path.end(); ++it) {
223 out.points.emplace_back(it->x(), it->y());
224 out.width.emplace_back(it_prev->z());
225 out.width.emplace_back(it->z());
226 it_prev = it;
227 }
228
229 return out;
230}
Definition Polyline.hpp:262
std::vector< coordf_t > width
Definition Polyline.hpp:281

References Slic3r::MultiPoint::points, and Slic3r::ThickPolyline::width.

Referenced by Slic3r::FillConcentric::_fill_surface_single(), Slic3r::FillSpiralInset::_fill_surface_single(), Slic3r::extrusion_paths_append(), Slic3r::extrusion_paths_append(), Slic3r::FillConcentricInternal::fill_surface_extrusion(), Slic3r::open_loop(), and Slic3r::traverse_loops().

Here is the caller graph for this function:

Variable Documentation

◆ fill_outline_gaps

bool Slic3r::Arachne::fill_outline_gaps = true
constexpr