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

#include <src/libslic3r/Arachne/SkeletalTrapezoidationGraph.hpp>

+ Inheritance diagram for Slic3r::Arachne::SkeletalTrapezoidationGraph:
+ Collaboration diagram for Slic3r::Arachne::SkeletalTrapezoidationGraph:

Public Types

using Edges = std::list< edge_t >
 
using Nodes = std::list< node_t >
 

Public Member Functions

void collapseSmallEdges (coord_t snap_dist=5)
 
void makeRib (edge_t *&prev_edge, Point start_source_point, Point end_source_point, bool is_next_to_start_or_end)
 
edge_tinsertNode (edge_t *edge, Point mid, coord_t mide_node_bead_count)
 
std::pair< edge_t *, edge_t * > insertRib (edge_t &edge, node_t *mid_node)
 

Public Attributes

Edges edges
 
Nodes nodes
 

Protected Member Functions

Line getSource (const edge_t &edge) const
 

Private Types

using edge_t = STHalfEdge
 
using node_t = STHalfEdgeNode
 

Detailed Description

Member Typedef Documentation

◆ edge_t

◆ Edges

◆ node_t

◆ Nodes

Member Function Documentation

◆ collapseSmallEdges()

void Slic3r::Arachne::SkeletalTrapezoidationGraph::collapseSmallEdges ( coord_t  snap_dist = 5)

If an edge is too small, collapse it and its twin and fix the surrounding edges to ensure a consistent graph.

Don't collapse support edges, unless we can collapse the whole quad.

o-, | "-o | | > Don't collapse this edge only. o o

183{
184 ankerl::unordered_dense::map<edge_t*, Edges::iterator> edge_locator;
185 ankerl::unordered_dense::map<node_t*, Nodes::iterator> node_locator;
186
187 for (auto edge_it = edges.begin(); edge_it != edges.end(); ++edge_it)
188 {
189 edge_locator.emplace(&*edge_it, edge_it);
190 }
191
192 for (auto node_it = nodes.begin(); node_it != nodes.end(); ++node_it)
193 {
194 node_locator.emplace(&*node_it, node_it);
195 }
196
197 auto safelyRemoveEdge = [this, &edge_locator](edge_t* to_be_removed, Edges::iterator& current_edge_it, bool& edge_it_is_updated)
198 {
199 if (current_edge_it != edges.end()
200 && to_be_removed == &*current_edge_it)
201 {
202 current_edge_it = edges.erase(current_edge_it);
203 edge_it_is_updated = true;
204 }
205 else
206 {
207 edges.erase(edge_locator[to_be_removed]);
208 }
209 };
210
211 auto should_collapse = [snap_dist](node_t* a, node_t* b)
212 {
213 return shorter_then(a->p - b->p, snap_dist);
214 };
215
216 for (auto edge_it = edges.begin(); edge_it != edges.end();)
217 {
218 if (edge_it->prev)
219 {
220 edge_it++;
221 continue;
222 }
223
224 edge_t* quad_start = &*edge_it;
225 edge_t* quad_end = quad_start; while (quad_end->next) quad_end = quad_end->next;
226 edge_t* quad_mid = (quad_start->next == quad_end)? nullptr : quad_start->next;
227
228 bool edge_it_is_updated = false;
229 if (quad_mid && should_collapse(quad_mid->from, quad_mid->to))
230 {
231 assert(quad_mid->twin);
232 if(!quad_mid->twin)
233 {
234 BOOST_LOG_TRIVIAL(warning) << "Encountered quad edge without a twin.";
235 continue; //Prevent accessing unallocated memory.
236 }
237 int count = 0;
238 for (edge_t* edge_from_3 = quad_end; edge_from_3 && edge_from_3 != quad_mid->twin; edge_from_3 = edge_from_3->twin->next)
239 {
240 edge_from_3->from = quad_mid->from;
241 edge_from_3->twin->to = quad_mid->from;
242 if (count > 50)
243 {
244 std::cerr << edge_from_3->from->p << " - " << edge_from_3->to->p << '\n';
245 }
246 if (++count > 1000)
247 {
248 break;
249 }
250 }
251
252 // o-o > collapse top
253 // | |
254 // | |
255 // | |
256 // o o
257 if (quad_mid->from->incident_edge == quad_mid)
258 {
259 if (quad_mid->twin->next)
260 {
261 quad_mid->from->incident_edge = quad_mid->twin->next;
262 }
263 else
264 {
265 quad_mid->from->incident_edge = quad_mid->prev->twin;
266 }
267 }
268
269 nodes.erase(node_locator[quad_mid->to]);
270
271 quad_mid->prev->next = quad_mid->next;
272 quad_mid->next->prev = quad_mid->prev;
273 quad_mid->twin->next->prev = quad_mid->twin->prev;
274 quad_mid->twin->prev->next = quad_mid->twin->next;
275
276 safelyRemoveEdge(quad_mid->twin, edge_it, edge_it_is_updated);
277 safelyRemoveEdge(quad_mid, edge_it, edge_it_is_updated);
278 }
279
280 // o-o
281 // | | > collapse sides
282 // o o
283 if ( should_collapse(quad_start->from, quad_end->to) && should_collapse(quad_start->to, quad_end->from))
284 { // Collapse start and end edges and remove whole cell
285
286 quad_start->twin->to = quad_end->to;
287 quad_end->to->incident_edge = quad_end->twin;
288 if (quad_end->from->incident_edge == quad_end)
289 {
290 if (quad_end->twin->next)
291 {
292 quad_end->from->incident_edge = quad_end->twin->next;
293 }
294 else
295 {
296 quad_end->from->incident_edge = quad_end->prev->twin;
297 }
298 }
299 nodes.erase(node_locator[quad_start->from]);
300
301 quad_start->twin->twin = quad_end->twin;
302 quad_end->twin->twin = quad_start->twin;
303 safelyRemoveEdge(quad_start, edge_it, edge_it_is_updated);
304 safelyRemoveEdge(quad_end, edge_it, edge_it_is_updated);
305 }
306 // If only one side had collapsable length then the cell on the other side of that edge has to collapse
307 // if we would collapse that one edge then that would change the quad_start and/or quad_end of neighboring cells
308 // this is to do with the constraint that !prev == !twin.next
309
310 if (!edge_it_is_updated)
311 {
312 edge_it++;
313 }
314 }
315}
edge_t * twin
Definition HalfEdge.hpp:24
edge_t * next
Definition HalfEdge.hpp:25
STHalfEdgeNode node_t
Definition SkeletalTrapezoidationGraph.hpp:76
STHalfEdge edge_t
Definition SkeletalTrapezoidationGraph.hpp:75
bool shorter_then(const Point &p0, const coord_t len)
Definition Point.hpp:301
IGL_INLINE void count(const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::SparseVector< SType > &S)
Definition count.cpp:12

References Slic3r::Arachne::HalfEdgeGraph< SkeletalTrapezoidationJoint, SkeletalTrapezoidationEdge, STHalfEdgeNode, STHalfEdge >::edges, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::from, Slic3r::Arachne::HalfEdgeNode< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::incident_edge, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::next, Slic3r::Arachne::HalfEdgeGraph< SkeletalTrapezoidationJoint, SkeletalTrapezoidationEdge, STHalfEdgeNode, STHalfEdge >::nodes, Slic3r::Arachne::HalfEdgeNode< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::p, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::prev, Slic3r::shorter_then(), Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::to, and Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::twin.

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

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

◆ getSource()

Line Slic3r::Arachne::SkeletalTrapezoidationGraph::getSource ( const edge_t edge) const
protected
456{
457 const edge_t *from_edge = &edge;
458 while (from_edge->prev)
459 from_edge = from_edge->prev;
460
461 const edge_t *to_edge = &edge;
462 while (to_edge->next)
463 to_edge = to_edge->next;
464
465 return Line(from_edge->from->p, to_edge->to->p);
466}
edge_t * prev
Definition HalfEdge.hpp:26

References Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::from, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::next, Slic3r::Arachne::HalfEdgeNode< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::p, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::prev, and Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::to.

Referenced by insertRib().

+ Here is the caller graph for this function:

◆ insertNode()

SkeletalTrapezoidationGraph::edge_t * Slic3r::Arachne::SkeletalTrapezoidationGraph::insertNode ( edge_t edge,
Point  mid,
coord_t  mide_node_bead_count 
)

Insert a node into the graph and connect it to the input polygon using ribs

Returns
the last edge which replaced [edge], which points to the same [to] node
429{
430 edge_t* last_edge_replacing_input = edge;
431
432 nodes.emplace_back(SkeletalTrapezoidationJoint(), mid);
433 node_t* mid_node = &nodes.back();
434
435 edge_t* twin = last_edge_replacing_input->twin;
436 last_edge_replacing_input->twin = nullptr;
437 twin->twin = nullptr;
438 std::pair<edge_t*, edge_t*> left_pair = insertRib(*last_edge_replacing_input, mid_node);
439 std::pair<edge_t*, edge_t*> right_pair = insertRib(*twin, mid_node);
440 edge_t* first_edge_replacing_input = left_pair.first;
441 last_edge_replacing_input = left_pair.second;
442 edge_t* first_edge_replacing_twin = right_pair.first;
443 edge_t* last_edge_replacing_twin = right_pair.second;
444
445 first_edge_replacing_input->twin = last_edge_replacing_twin;
446 last_edge_replacing_twin->twin = first_edge_replacing_input;
447 last_edge_replacing_input->twin = first_edge_replacing_twin;
448 first_edge_replacing_twin->twin = last_edge_replacing_input;
449
450 mid_node->data.bead_count = mide_node_bead_count;
451
452 return last_edge_replacing_input;
453}
edge_data_t data
Definition HalfEdge.hpp:23
std::pair< edge_t *, edge_t * > insertRib(edge_t &edge, node_t *mid_node)
Definition SkeletalTrapezoidationGraph.cpp:347

References Slic3r::Arachne::SkeletalTrapezoidationJoint::bead_count, Slic3r::Arachne::HalfEdgeNode< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::data, insertRib(), Slic3r::Arachne::HalfEdgeGraph< SkeletalTrapezoidationJoint, SkeletalTrapezoidationEdge, STHalfEdgeNode, STHalfEdge >::nodes, and Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::twin.

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

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

◆ insertRib()

std::pair< SkeletalTrapezoidationGraph::edge_t *, SkeletalTrapezoidationGraph::edge_t * > Slic3r::Arachne::SkeletalTrapezoidationGraph::insertRib ( edge_t edge,
node_t mid_node 
)

Return the first and last edge of the edges replacing edge pointing to the same node

348{
349 edge_t* edge_before = edge.prev;
350 edge_t* edge_after = edge.next;
351 node_t* node_before = edge.from;
352 node_t* node_after = edge.to;
353
354 Point p = mid_node->p;
355
356 const Line source_segment = getSource(edge);
357 Point px;
358 source_segment.distance_to_squared(p, &px);
359 coord_t dist = (p - px).cast<int64_t>().norm();
360 assert(dist > 0);
361 mid_node->data.distance_to_boundary = dist;
362 mid_node->data.transition_ratio = 0; // Both transition end should have rest = 0, because at the ends a whole number of beads fits without rest
363
364 nodes.emplace_back(SkeletalTrapezoidationJoint(), px);
365 node_t* source_node = &nodes.back();
366 source_node->data.distance_to_boundary = 0;
367
368 edge_t* first = &edge;
369 edges.emplace_back(SkeletalTrapezoidationEdge());
370 edge_t* second = &edges.back();
371 edges.emplace_back(SkeletalTrapezoidationEdge(SkeletalTrapezoidationEdge::EdgeType::TRANSITION_END));
372 edge_t* outward_edge = &edges.back();
373 edges.emplace_back(SkeletalTrapezoidationEdge(SkeletalTrapezoidationEdge::EdgeType::TRANSITION_END));
374 edge_t* inward_edge = &edges.back();
375
376 if (edge_before)
377 {
378 edge_before->next = first;
379 }
380 first->next = outward_edge;
381 outward_edge->next = nullptr;
382 inward_edge->next = second;
383 second->next = edge_after;
384
385 if (edge_after)
386 {
387 edge_after->prev = second;
388 }
389 second->prev = inward_edge;
390 inward_edge->prev = nullptr;
391 outward_edge->prev = first;
392 first->prev = edge_before;
393
394 first->to = mid_node;
395 outward_edge->to = source_node;
396 inward_edge->to = mid_node;
397 second->to = node_after;
398
399 first->from = node_before;
400 outward_edge->from = mid_node;
401 inward_edge->from = source_node;
402 second->from = mid_node;
403
404 node_before->incident_edge = first;
405 mid_node->incident_edge = outward_edge;
406 source_node->incident_edge = inward_edge;
407 if (edge_after)
408 {
409 node_after->incident_edge = edge_after;
410 }
411
412 first->data.setIsCentral(true);
413 outward_edge->data.setIsCentral(false); // TODO verify this is always the case.
414 inward_edge->data.setIsCentral(false);
415 second->data.setIsCentral(true);
416
417 outward_edge->twin = inward_edge;
418 inward_edge->twin = outward_edge;
419
420 first->twin = nullptr; // we don't know these yet!
421 second->twin = nullptr;
422
423 assert(second->prev->from->data.distance_to_boundary == 0);
424
425 return std::make_pair(first, second);
426}
Point p
Definition HalfEdgeNode.hpp:24
Line getSource(const edge_t &edge) const
Definition SkeletalTrapezoidationGraph.cpp:455
int32_t coord_t
Definition libslic3r.h:39
T dist(const boost::polygon::point_data< T > &p1, const boost::polygon::point_data< T > &p2)
Definition Geometry.cpp:280
Kernel::Point_2 Point
Definition point_areas.cpp:20

References Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::data, Slic3r::Arachne::HalfEdgeNode< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::data, Slic3r::Arachne::SkeletalTrapezoidationJoint::distance_to_boundary, Slic3r::Line::distance_to_squared(), Slic3r::Arachne::HalfEdgeGraph< SkeletalTrapezoidationJoint, SkeletalTrapezoidationEdge, STHalfEdgeNode, STHalfEdge >::edges, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::from, getSource(), Slic3r::Arachne::HalfEdgeNode< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::incident_edge, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::next, Slic3r::Arachne::HalfEdgeGraph< SkeletalTrapezoidationJoint, SkeletalTrapezoidationEdge, STHalfEdgeNode, STHalfEdge >::nodes, Slic3r::Arachne::HalfEdgeNode< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::p, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::prev, Slic3r::Arachne::SkeletalTrapezoidationEdge::setIsCentral(), Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::to, Slic3r::Arachne::SkeletalTrapezoidationEdge::TRANSITION_END, Slic3r::Arachne::SkeletalTrapezoidationJoint::transition_ratio, and Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::twin.

Referenced by insertNode().

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

◆ makeRib()

void Slic3r::Arachne::SkeletalTrapezoidationGraph::makeRib ( edge_t *&  prev_edge,
Point  start_source_point,
Point  end_source_point,
bool  is_next_to_start_or_end 
)
318{
319 Point p;
320 Line(start_source_point, end_source_point).distance_to_infinite_squared(prev_edge->to->p, &p);
321 coord_t dist = (prev_edge->to->p - p).cast<int64_t>().norm();
322 prev_edge->to->data.distance_to_boundary = dist;
323 assert(dist >= 0);
324
325 nodes.emplace_front(SkeletalTrapezoidationJoint(), p);
326 node_t* node = &nodes.front();
327 node->data.distance_to_boundary = 0;
328
329 edges.emplace_front(SkeletalTrapezoidationEdge(SkeletalTrapezoidationEdge::EdgeType::EXTRA_VD));
330 edge_t* forth_edge = &edges.front();
331 edges.emplace_front(SkeletalTrapezoidationEdge(SkeletalTrapezoidationEdge::EdgeType::EXTRA_VD));
332 edge_t* back_edge = &edges.front();
333
334 prev_edge->next = forth_edge;
335 forth_edge->prev = prev_edge;
336 forth_edge->from = prev_edge->to;
337 forth_edge->to = node;
338 forth_edge->twin = back_edge;
339 back_edge->twin = forth_edge;
340 back_edge->from = node;
341 back_edge->to = prev_edge->to;
342 node->incident_edge = back_edge;
343
344 prev_edge = back_edge;
345}

References Slic3r::Arachne::HalfEdgeNode< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::data, Slic3r::Arachne::SkeletalTrapezoidationJoint::distance_to_boundary, Slic3r::Line::distance_to_infinite_squared(), Slic3r::Arachne::HalfEdgeGraph< SkeletalTrapezoidationJoint, SkeletalTrapezoidationEdge, STHalfEdgeNode, STHalfEdge >::edges, Slic3r::Arachne::SkeletalTrapezoidationEdge::EXTRA_VD, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::from, Slic3r::Arachne::HalfEdgeNode< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::incident_edge, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::next, Slic3r::Arachne::HalfEdgeGraph< SkeletalTrapezoidationJoint, SkeletalTrapezoidationEdge, STHalfEdgeNode, STHalfEdge >::nodes, Slic3r::Arachne::HalfEdgeNode< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::p, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::prev, Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::to, and Slic3r::Arachne::HalfEdge< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::twin.

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::constructFromPolygons(), and Slic3r::Arachne::SkeletalTrapezoidation::transferEdge().

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

Member Data Documentation

◆ edges

◆ nodes


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