MCPcopy Create free account
hub / github.com/MeshInspector/MeshLib / canCollapse_

Method canCollapse_

source/MRMesh/MRMeshDecimate.cpp:539–721  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

537}
538
539auto MeshDecimator::canCollapse_( EdgeId edgeToCollapse, const Vector3f & collapsePos ) -> CanCollapseRes
540{
541 const auto & topology = mesh_.topology;
542 auto vl = topology.left( edgeToCollapse ).valid() ? topology.dest( topology.next( edgeToCollapse ) ) : VertId{};
543 auto vr = topology.right( edgeToCollapse ).valid() ? topology.dest( topology.prev( edgeToCollapse ) ) : VertId{};
544
545 // cannot collapse internal edge if its left and right faces share another edge
546 if ( vl && vr )
547 {
548 bool oDegree2 = false;
549 if ( auto pe = topology.prev( edgeToCollapse ); pe != edgeToCollapse && pe == topology.next( edgeToCollapse ) )
550 oDegree2 = true; // (pe) is shared between left and right faces of edgeToCollapse
551
552 bool dDegree2 = false;
553 if ( auto pe = topology.prev( edgeToCollapse.sym() ); pe != edgeToCollapse.sym() && pe == topology.next( edgeToCollapse.sym() ) )
554 dDegree2 = true; // (pe) is shared between left and right faces of edgeToCollapse
555
556 // if both oDegree2 and dDegree2 are true, then vl == vr
557 assert( !oDegree2 || !dDegree2 || vl == vr );
558
559 // but can collapse if left and right faces of edgeToCollapse share all 3 edges
560 if ( oDegree2 != dDegree2 )
561 return { .status = CollapseStatus::SharedEdge };
562 }
563 const bool collapsingFlippable = !settings_.notFlippable || !settings_.notFlippable->test( edgeToCollapse );
564
565 auto vo = topology.org( edgeToCollapse );
566 auto vd = topology.dest( edgeToCollapse );
567 auto po = mesh_.points[vo];
568 auto pd = mesh_.points[vd];
569 if ( collapsePos == pd )
570 {
571 // reverse the edge to have its origin in remaining fixed vertex
572 edgeToCollapse = edgeToCollapse.sym();
573 std::swap( vo, vd );
574 std::swap( vl, vr );
575 std::swap( po, pd );
576 }
577
578 auto smallShift = [maxBdShiftSq = sqr( settings_.maxBdShift )]( const LineSegm3f & segm, const Vector3f & p )
579 {
580 return ( closestPointOnLineSegm( p, segm ) - p ).lengthSq() <= maxBdShiftSq;
581 };
582 if ( ( !vl || !vr ) && settings_.maxBdShift < FLT_MAX )
583 {
584 if ( !smallShift( mesh_.edgeSegment( edgeToCollapse ), collapsePos ) )
585 return { .status = CollapseStatus::PosFarBd }; // new vertex is too far from collapsing boundary edge
586 if ( !vr )
587 {
588 if ( !smallShift( LineSegm3f{ mesh_.orgPnt( mesh_.topology.prevLeftBd( edgeToCollapse ) ), collapsePos }, po ) )
589 return { .status = CollapseStatus::PosFarBd }; // origin of collapsing boundary edge is too far from new boundary segment
590 if ( !smallShift( LineSegm3f{ mesh_.destPnt( mesh_.topology.nextLeftBd( edgeToCollapse ) ), collapsePos }, pd ) )
591 return { .status = CollapseStatus::PosFarBd }; // destination of collapsing boundary edge is too far from new boundary segment
592 }
593 if ( !vl )
594 {
595 if ( !smallShift( LineSegm3f{ mesh_.orgPnt( mesh_.topology.prevLeftBd( edgeToCollapse.sym() ) ), collapsePos }, pd ) )
596 return { .status = CollapseStatus::PosFarBd }; // destination of collapsing boundary edge is too far from new boundary segment

Callers

nothing calls this directly

Calls 15

closestPointOnLineSegmFunction · 0.85
maxFunction · 0.85
orgRing0Function · 0.85
leftMethod · 0.80
rightMethod · 0.80
prevLeftBdMethod · 0.80
nextLeftBdMethod · 0.80
push_backMethod · 0.80
isLeftBdEdgeMethod · 0.80
swapFunction · 0.70
sqrFunction · 0.70
crossFunction · 0.70

Tested by

no test coverage detected