OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::Arachne::PolylineStitcher< Paths, Path, Junction > Class Template Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Arachne/utils/PolylineStitcher.hpp>

Public Member Functions

bool canReverse (const PathsPointIndex< VariableWidthLines > &ppi)
bool canReverse (const PathsPointIndex< Polygons > &)
bool canConnect (const ExtrusionLine &a, const ExtrusionLine &b)
bool canConnect (const Polygon &, const Polygon &)
bool isOdd (const ExtrusionLine &line)
bool isOdd (const Polygon &)

Static Public Member Functions

static void stitch (const Paths &lines, Paths &result_lines, Paths &result_polygons, coord_t max_stitch_distance=scaled< coord_t >(0.1), coord_t snap_distance=scaled< coord_t >(0.01))
static bool canReverse (const PathsPointIndex< Paths > &polyline)
static bool canConnect (const Path &a, const Path &b)
static bool isOdd (const Path &line)

Detailed Description

template<typename Paths, typename Path, typename Junction>
class Slic3r::Arachne::PolylineStitcher< Paths, Path, Junction >

Class for stitching polylines into longer polylines or into polygons

Member Function Documentation

◆ canConnect() [1/3]

33{
34 return a.is_odd == b.is_odd;
35}
Definition PolylineStitcher.hpp:29

References Slic3r::Arachne::ExtrusionLine::is_odd.

◆ canConnect() [2/3]

template<typename Paths, typename Path, typename Junction>
bool Slic3r::Arachne::PolylineStitcher< Paths, Path, Junction >::canConnect ( const Path & a,
const Path & b )
static

Whether two paths are allowed to be connected. (Not true for an odd and an even wall.)

Referenced by stitch().

Here is the caller graph for this function:

◆ canConnect() [3/3]

bool Slic3r::Arachne::PolylineStitcher< Polygons, Polygon, Point >::canConnect ( const Polygon & ,
const Polygon &  )
38{
39 return true;
40}

◆ canReverse() [1/3]

template<typename Paths, typename Path, typename Junction>
bool Slic3r::Arachne::PolylineStitcher< Paths, Path, Junction >::canReverse ( const PathsPointIndex< Paths > & polyline)
static

Whether a polyline is allowed to be reversed. (Not true for wall polylines which are not odd)

Referenced by stitch().

Here is the caller graph for this function:

◆ canReverse() [2/3]

28{
29 return true;
30}

◆ canReverse() [3/3]

20{
21 if ((*ppi.polygons)[ppi.poly_idx].is_odd)
22 return true;
23 else
24 return false;
25}

References Slic3r::Arachne::PathsPointIndex< Paths >::poly_idx, and Slic3r::Arachne::PathsPointIndex< Paths >::polygons.

◆ isOdd() [1/3]

◆ isOdd() [2/3]

template<typename Paths, typename Path, typename Junction>
bool Slic3r::Arachne::PolylineStitcher< Paths, Path, Junction >::isOdd ( const Path & line)
static

Referenced by stitch().

Here is the caller graph for this function:

◆ isOdd() [3/3]

48{
49 return false;
50}

◆ stitch()

template<typename Paths, typename Path, typename Junction>
void Slic3r::Arachne::PolylineStitcher< Paths, Path, Junction >::stitch ( const Paths & lines,
Paths & result_lines,
Paths & result_polygons,
coord_t max_stitch_distance = scaled<coord_t>(0.1),
coord_t snap_distance = scaled<coord_t>(0.01) )
inlinestatic

Stitch together the separate lines into result_lines and if they can be closed into result_polygons.

Only introduce new segments shorter than max_stitch_distance, and larger than snap_distance but always try to take the shortest connection possible.

Only stitch polylines into closed polygons if they are larger than 3 * max_stitch_distance, in order to prevent small segments to accidentally get closed into a polygon.

Warning
Tiny polylines (smaller than 3 * max_stitch_distance) will not be closed into polygons.
Note
Resulting polylines and polygons are added onto the existing containers, so you can directly output onto a polygons container with existing polygons in it. However, you shouldn't call this function with the same parameter in lines as result_lines, because that would duplicate (some of) the polylines.
Parameters
linesThe lines to stitch together.
result_lines[out]The stitched parts that are not closed polygons will be stored in here.
result_polygons[out]The stitched parts that were closed as polygons will be stored in here.
max_stitch_distanceThe maximum distance that will be bridged to connect two lines.
snap_distancePoints closer than this distance are considered to be the same point.
62 {
63 if (lines.empty())
64 return;
65
67
68 // populate grid
69 for (size_t line_idx = 0; line_idx < lines.size(); line_idx++)
70 {
71 const auto line = lines[line_idx];
73 grid.insert(PathsPointIndex<Paths>(&lines, line_idx, line.size() - 1));
74 }
75
76 std::vector<bool> processed(lines.size(), false);
77
78 for (size_t line_idx = 0; line_idx < lines.size(); line_idx++)
79 {
81 {
82 continue;
83 }
84 processed[line_idx] = true;
85 const auto line = lines[line_idx];
86 bool should_close = isOdd(line);
87
88 Path chain = line;
89 bool closest_is_closing_polygon = false;
90 for (bool go_in_reverse_direction : { false, true }) // first go in the unreversed direction, to try to prevent the chain.reverse() operation.
91 { // NOTE: Implementation only works for this order; we currently only re-reverse the chain when it's closed.
93 { // try extending chain in the other direction
94 chain.reverse();
95 }
96 int64_t chain_length = chain.polylineLength();
97
98 while (true)
99 {
100 Point from = make_point(chain.back());
101
104 grid.processNearby(from, max_stitch_distance,
107 (const PathsPointIndex<Paths>& nearby)->bool
108 {
109 bool is_closing_segment = false;
110 coord_t dist = (nearby.p().template cast<int64_t>() - from.template cast<int64_t>()).norm();
112 {
113 return true; // keep looking
114 }
115 if ((nearby.p().template cast<int64_t>() - make_point(chain.front()).template cast<int64_t>()).squaredNorm() < snap_distance * snap_distance)
116 {
117 if (chain_length + dist < 3 * max_stitch_distance // prevent closing of small poly, cause it might be able to continue making a larger polyline
118 || chain.size() <= 2) // don't make 2 vert polygons
119 {
120 return true; // look for a better next line
121 }
122 is_closing_segment = true;
123 if (!should_close)
124 {
125 dist += scaled<coord_t>(0.01); // prefer continuing polyline over closing a polygon; avoids closed zigzags from being printed separately
126 // continue to see if closing segment is also the closest
127 // there might be a segment smaller than [max_stitch_distance] which closes the polygon better
128 }
129 else
130 {
131 dist -= scaled<coord_t>(0.01); //Prefer closing the polygon if it's 100% even lines. Used to create closed contours.
132 //Continue to see if closing segment is also the closest.
133 }
134 }
135 else if (processed[nearby.poly_idx])
136 { // it was already moved to output
137 return true; // keep looking for a connection
138 }
139 bool nearby_would_be_reversed = nearby.point_idx != 0;
140 nearby_would_be_reversed = nearby_would_be_reversed != go_in_reverse_direction; // flip nearby_would_be_reversed when searching in the reverse direction
142 { // connecting the segment would reverse the polygon direction
143 return true; // keep looking for a connection
144 }
145 if (!canConnect(chain, (*nearby.polygons)[nearby.poly_idx]))
146 {
147 return true; // keep looking for a connection
148 }
150 {
152 closest = nearby;
154 }
155 if (dist < snap_distance)
156 { // we have found a good enough next line
157 return false; // stop looking for alternatives
158 }
159 return true; // keep processing elements
160 })
161 );
162
163 if (!closest.initialized() // we couldn't find any next line
164 || closest_is_closing_polygon // we closed the polygon
165 )
166 {
167 break;
168 }
169
170 coord_t segment_dist = (make_point(chain.back()).template cast<int64_t>() - closest.p().template cast<int64_t>()).norm();
172 const size_t old_size = chain.size();
173 if (closest.point_idx == 0)
174 {
175 auto start_pos = (*closest.polygons)[closest.poly_idx].begin();
177 {
178 ++start_pos;
179 }
180 chain.insert(chain.end(), start_pos, (*closest.polygons)[closest.poly_idx].end());
181 }
182 else
183 {
184 auto start_pos = (*closest.polygons)[closest.poly_idx].rbegin();
186 {
187 ++start_pos;
188 }
189 chain.insert(chain.end(), start_pos, (*closest.polygons)[closest.poly_idx].rend());
190 }
191 for(size_t i = old_size; i < chain.size(); ++i) //Update chain length.
192 {
193 chain_length += (make_point(chain[i]).template cast<int64_t>() - make_point(chain[i - 1]).template cast<int64_t>()).norm();
194 }
195 should_close = should_close & !isOdd((*closest.polygons)[closest.poly_idx]); //If we connect an even to an odd line, we should no longer try to close it.
196 assert( ! processed[closest.poly_idx]);
197 processed[closest.poly_idx] = true;
198 }
200 {
202 { // re-reverse chain to retain original direction
203 // NOTE: not sure if this code could ever be reached, since if a polygon can be closed that should be already possible in the forward direction
204 chain.reverse();
205 }
206
207 break; // don't consider reverse direction
208 }
209 }
211 {
212 result_polygons.emplace_back(chain);
213 }
214 else
215 {
217 if ( ! canReverse(ppi_here))
218 { // Since closest_is_closing_polygon is false we went through the second iterations of the for-loop, where go_in_reverse_direction is true
219 // the polyline isn't allowed to be reversed, so we re-reverse it.
220 chain.reverse();
221 }
222 result_lines.emplace_back(chain);
223 }
224 }
225 }
static bool canReverse(const PathsPointIndex< Paths > &polyline)
static bool isOdd(const Path &line)
static bool canConnect(const Path &a, const Path &b)
const Point & make_point(const ExtrusionJunction &ej)
Definition ExtrusionJunction.hpp:60
BoundingBox scaled(const BoundingBoxf &bb)
Definition BoundingBox.hpp:284
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:127
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299

References canConnect(), canReverse(), Slic3r::cast(), Slic3r::Geometry::dist(), Slic3r::grid(), isOdd(), Slic3r::Arachne::make_point(), Slic3r::Arachne::PathsPointIndex< Paths >::p(), Slic3r::Arachne::PathsPointIndex< Paths >::point_idx, Slic3r::Arachne::PathsPointIndex< Paths >::poly_idx, Slic3r::Arachne::PathsPointIndex< Paths >::polygons, and Slic3r::scaled().

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

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

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