| 695 | } |
| 696 | |
| 697 | bool MultiwayICP::updateLayerPairs_( ICPLayer l, const ProgressCallback& cb ) |
| 698 | { |
| 699 | MR_TIMER; |
| 700 | auto numGroups = pairsGridPerLayer_[l].size(); |
| 701 | bool cascadeMode = pairsGridPerLayer_.size() > 1; |
| 702 | |
| 703 | assert( l == 0 || cascadeMode ); |
| 704 | assert( l < pairsGridPerLayer_.size() ); |
| 705 | |
| 706 | // build trees |
| 707 | using LayerTrees = Vector<AABBTreeObjects, ICPElementId>; |
| 708 | using LayerMaps = Vector<ObjMap, ICPElementId>; |
| 709 | LayerTrees trees; |
| 710 | LayerMaps maps; |
| 711 | if ( l == 0 ) |
| 712 | { |
| 713 | for ( const auto& obj : objs_ ) |
| 714 | obj.obj.cacheAABBTree(); // trigger AABB Tree build if needed not to fall in deep stack while projecting |
| 715 | } |
| 716 | else |
| 717 | { |
| 718 | // only for upper layers |
| 719 | trees.resize( numGroups ); |
| 720 | maps.resize( numGroups ); |
| 721 | ParallelFor( trees, [&] ( ICPElementId gI ) |
| 722 | { |
| 723 | const auto& leaves = cascadeIndexer_->getElementLeaves( l, gI ); |
| 724 | maps[gI].reserve( leaves.count() ); |
| 725 | ICPObjects leafObjs; |
| 726 | leafObjs.reserve( leaves.count() ); |
| 727 | for ( auto leaf : leaves ) |
| 728 | { |
| 729 | maps[gI].emplace_back( leaf ); |
| 730 | leafObjs.emplace_back( objs_[leaf] ); |
| 731 | } |
| 732 | trees[gI] = AABBTreeObjects( std::move( leafObjs ) ); |
| 733 | } ); |
| 734 | } |
| 735 | |
| 736 | auto createProjector = [&] ( ICPElementId elId )->ICPGroupProjector |
| 737 | { |
| 738 | if ( l == 0 ) |
| 739 | return [this, elId] ( const Vector3f& p, MeshOrPoints::ProjectionResult& res, ObjId& resId ) mutable |
| 740 | { |
| 741 | auto proj = objs_[ObjId( elId.get() )].obj.limitedProjector(); |
| 742 | proj( objs_[ObjId( elId.get() )].xf.inverse()( p ), res ); |
| 743 | if ( res.closestVert ) |
| 744 | resId = ObjId( elId.get() ); |
| 745 | }; |
| 746 | return [&trees, &maps, elId] ( const Vector3f& p, MeshOrPoints::ProjectionResult& res, ObjId& resId ) |
| 747 | { |
| 748 | projectOnAll( p, trees[elId], res.distSq, [&] ( ObjId oId, MeshOrPoints::ProjectionResult prj ) |
| 749 | { |
| 750 | if ( prj.distSq >= res.distSq ) |
| 751 | return; |
| 752 | res = prj; |
| 753 | resId = maps[elId][oId]; |
| 754 | } ); |
nothing calls this directly
no test coverage detected