OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::Arachne::SkeletalTrapezoidationGraph Class Reference

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

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

Public Types

using Edges
using Nodes

Public Member Functions

void collapseSmallEdges (coord_t snap_dist=5)
void makeRib (edge_t *&prev_edge, const Point &start_source_point, const Point &end_source_point)
edge_t * insertNode (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

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

References count, 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.

Here is the call graph for this function:

◆ getSource()

Line Slic3r::Arachne::SkeletalTrapezoidationGraph::getSource ( const edge_t & edge) const
protected
466{
467 const edge_t *from_edge = &edge;
468 while (from_edge->prev)
469 from_edge = from_edge->prev;
470
471 const edge_t *to_edge = &edge;
472 while (to_edge->next)
473 to_edge = to_edge->next;
474
475 return Line(from_edge->from->p, to_edge->to->p);
476}

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
439{
440 edge_t* last_edge_replacing_input = edge;
441
442 nodes.emplace_back(SkeletalTrapezoidationJoint(), mid);
443 node_t* mid_node = &nodes.back();
444
445 edge_t* twin = last_edge_replacing_input->twin;
446 last_edge_replacing_input->twin = nullptr;
447 twin->twin = nullptr;
448 std::pair<edge_t*, edge_t*> left_pair = insertRib(*last_edge_replacing_input, mid_node);
449 std::pair<edge_t*, edge_t*> right_pair = insertRib(*twin, mid_node);
450 edge_t* first_edge_replacing_input = left_pair.first;
451 last_edge_replacing_input = left_pair.second;
452 edge_t* first_edge_replacing_twin = right_pair.first;
453 edge_t* last_edge_replacing_twin = right_pair.second;
454
455 first_edge_replacing_input->twin = last_edge_replacing_twin;
456 last_edge_replacing_twin->twin = first_edge_replacing_input;
457 last_edge_replacing_input->twin = first_edge_replacing_twin;
458 first_edge_replacing_twin->twin = last_edge_replacing_input;
459
460 mid_node->data.bead_count = mide_node_bead_count;
461
462 return last_edge_replacing_input;
463}
std::pair< edge_t *, edge_t * > insertRib(edge_t &edge, node_t *mid_node)
Definition SkeletalTrapezoidationGraph.cpp:357

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.

Here is the call 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

358{
359 edge_t* edge_before = edge.prev;
360 edge_t* edge_after = edge.next;
361 node_t* node_before = edge.from;
362 node_t* node_after = edge.to;
363
364 Point p = mid_node->p;
365
366 const Line source_segment = getSource(edge);
367 Point px;
368 source_segment.distance_to_squared(p, &px);
369 coord_t dist = (p - px).cast<int64_t>().norm();
370 assert(dist > 0);
371 mid_node->data.distance_to_boundary = dist;
372 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
373
374 nodes.emplace_back(SkeletalTrapezoidationJoint(), px);
375 node_t* source_node = &nodes.back();
376 source_node->data.distance_to_boundary = 0;
377
378 edge_t* first = &edge;
379 edges.emplace_back(SkeletalTrapezoidationEdge());
380 edge_t* second = &edges.back();
381 edges.emplace_back(SkeletalTrapezoidationEdge(SkeletalTrapezoidationEdge::EdgeType::TRANSITION_END));
382 edge_t* outward_edge = &edges.back();
383 edges.emplace_back(SkeletalTrapezoidationEdge(SkeletalTrapezoidationEdge::EdgeType::TRANSITION_END));
384 edge_t* inward_edge = &edges.back();
385
386 if (edge_before)
387 {
388 edge_before->next = first;
389 }
390 first->next = outward_edge;
391 outward_edge->next = nullptr;
392 inward_edge->next = second;
393 second->next = edge_after;
394
395 if (edge_after)
396 {
397 edge_after->prev = second;
398 }
399 second->prev = inward_edge;
400 inward_edge->prev = nullptr;
401 outward_edge->prev = first;
402 first->prev = edge_before;
403
404 first->to = mid_node;
405 outward_edge->to = source_node;
406 inward_edge->to = mid_node;
407 second->to = node_after;
408
409 first->from = node_before;
410 outward_edge->from = mid_node;
411 inward_edge->from = source_node;
412 second->from = mid_node;
413
414 node_before->incident_edge = first;
415 mid_node->incident_edge = outward_edge;
416 source_node->incident_edge = inward_edge;
417 if (edge_after)
418 {
419 node_after->incident_edge = edge_after;
420 }
421
422 first->data.setIsCentral(true);
423 outward_edge->data.setIsCentral(false); // TODO verify this is always the case.
424 inward_edge->data.setIsCentral(false);
425 second->data.setIsCentral(true);
426
427 outward_edge->twin = inward_edge;
428 inward_edge->twin = outward_edge;
429
430 first->twin = nullptr; // we don't know these yet!
431 second->twin = nullptr;
432
433 assert(second->prev->from->data.distance_to_boundary == 0);
434
435 return std::make_pair(first, second);
436}
@ TRANSITION_END
Definition SkeletalTrapezoidationEdge.hpp:55
Line getSource(const edge_t &edge) const
Definition SkeletalTrapezoidationGraph.cpp:465
int64_t coord_t
Definition libslic3r.h:48
T dist(const boost::polygon::point_data< T > &p1, const boost::polygon::point_data< T > &p2)
Definition Geometry.cpp:298
int64_t px(const Point &pt)
Definition ClipperUtils.cpp:207
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299

References Slic3r::cast(), 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::Geometry::dist(), 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,
const Point & start_source_point,
const Point & end_source_point )
328 {
329 Point p;
330 Line(start_source_point, end_source_point).distance_to_infinite_squared(prev_edge->to->p, &p);
331 coord_t dist = (prev_edge->to->p - p).cast<int64_t>().norm();
332 prev_edge->to->data.distance_to_boundary = dist;
333 assert(dist >= 0);
334
335 nodes.emplace_front(SkeletalTrapezoidationJoint(), p);
336 node_t* node = &nodes.front();
337 node->data.distance_to_boundary = 0;
338
339 edges.emplace_front(SkeletalTrapezoidationEdge(SkeletalTrapezoidationEdge::EdgeType::EXTRA_VD));
340 edge_t* forth_edge = &edges.front();
341 edges.emplace_front(SkeletalTrapezoidationEdge(SkeletalTrapezoidationEdge::EdgeType::EXTRA_VD));
342 edge_t* back_edge = &edges.front();
343
344 prev_edge->next = forth_edge;
345 forth_edge->prev = prev_edge;
346 forth_edge->from = prev_edge->to;
347 forth_edge->to = node;
348 forth_edge->twin = back_edge;
349 back_edge->twin = forth_edge;
350 back_edge->from = node;
351 back_edge->to = prev_edge->to;
352 node->incident_edge = back_edge;
353
354 prev_edge = back_edge;
355}
@ EXTRA_VD
Definition SkeletalTrapezoidationEdge.hpp:54

References Slic3r::cast(), Slic3r::Arachne::HalfEdgeNode< node_data_t, edge_data_t, derived_node_t, derived_edge_t >::data, Slic3r::Geometry::dist(), 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.

Here is the call graph for this function:

Member Data Documentation

◆ edges

◆ nodes


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